Go Plus Script
Posted: Mon Jul 21, 2014 1:49 am
This Zeus script automates the checking of Go code for correctness by running the go fmt, goimports, golint, go vet and go build commands each time the file is saved.
Refer to the script comments for details on how to use this script.
Refer to the script comments for details on how to use this script.
Code: Select all
#
# Name: Go Plus Script
#
# Author: Jussi Jumppanen
#
# Language: Python
#
# Description: This script will run gofmt, goimports, golint, go vet and
# go build on the current file and capture any error output produced.
#
# The script will run the following Go command on the current file
# in the order listed:
#
# gofmt
# goimports
# golint
# go vet
# go build
#
# If any errors are detected they will be reported to the user with
# the line number, error message and file name allowing the user to
# quickly navigate to the error.
#
# This macro assumes the imports, vet and lint packages have been
# downloaded, built and correctly installed:
#
# lint - https://github.com/golang/lint
# imports - http://godoc.org/code.google.com/p/go.tools/cmd/goimports
# vet - http://godoc.org/code.google.com/p/go.tools/cmd/vet
#
# To make this script run on file save just use the Options, Editor Options
# menu and in the Triggers panel set this as the File Save Portfix script:
#
# $zud\zScript\go_plus.py
#
import os
import zeus
import os.path
def goplus_trigger():
# get the document type for the current file
document_type = zeus.macro_tag("$DTD")
if (document_type != "Go Document Type"):
# ignore this file as it is not a Go document type
return 1
# macro only works for documents
document = zeus.is_document()
# macro only works for read/write documents.
locked = zeus.is_read_only()
# macro only works for named documents.
named = zeus.is_named()
if (locked == 1) or (document == 0) or (named == 0):
# can't run the format on current document
zeus.message("This macro only works with named, writable Go documents.")
zeus.beep()
return 0
# the details of the current document
file_base = zeus.macro_tag("$f")
file_name = zeus.macro_tag("$fn")
# the output file name
file_output = file_name + ".ztow"
# the compiler error name
file_error = file_name + ".zerr"
# remove any previous output file
if os.access(file_output, os.F_OK):
os.remove(file_output)
# remove any previous error file
if os.access(file_error, os.F_OK):
os.remove(file_error)
result = 0
if result == 0:
# run gofmt
result = go_fmt(file_name, file_output)
if result == 0:
# run goimports command
result = go_imports(file_name, file_output)
if result == 0:
# run go lint command
result = go_lint(file_name, file_output)
if result == 0:
# run go vet command
result = go_vet(file_name, file_output)
if result == 0:
# run go build command
result = go_build(file_name, file_output)
if result == 0:
zeus.message("File: '" + file_base + "' save completed.")
def go_build(file_name, file_output):
# the go build command
return run_cmd("go build", file_name, file_output)
def go_fmt(file_name, file_output):
# -------------------------------------------------------------------------
# -- usage: gofmt [flags] [path ...]
# -------------------------------------------------------------------------
# -- -cpuprofile="": write cpu profile to this file
# -- -d=false: display diffs instead of rewriting files
# -- -e=false: report all errors (not just the first 10 on different lines)
# -- -l=false: list files whose formatting differs from gofmt's
# -- -r="": rewrite rule (e.g., 'a[b:len(a)] -> a[b:]')
# -- -s=false: simplify code
# -- -w=false: write result to (source) file instead of stdout
# -------------------------------------------------------------------------
# the gofmt command
return run_cmd("gofmt.exe -w=true -e=true", file_name, file_output)
def go_imports(file_name, file_output):
# the goimports command
return run_cmd("goimports.exe -w=true", file_name, file_output)
def go_lint(file_name, file_output):
# the golint command
return run_cmd("golint.exe", file_name, file_output)
def go_vet(file_name, file_output):
# the goimports command
return run_cmd("go vet", file_name, file_output)
def check_file_errors(file_errors):
# see if any output was produced
have_errors = 0
if (os.path.isfile(file_errors)):
statinfo = os.stat(file_errors)
if statinfo.st_size > 0:
have_errors = 1
return have_errors
def check_lfn(file_name):
# check if file contains any whitespace
if (file_name.find(' ') <> -1):
# add quotes to the output file name
file_name = '"' + file_name + '"'
return file_name
def run_cmd(cmd, file_name, file_errors):
# run the command as a DOS command in hidden window and wait for it to finish
flags = 16+32
# check all files for LFN details and pipe stdout, stderr to the errors file
cmd = cmd + " " + check_lfn(file_name) + " > " + check_lfn(file_errors) + " 2>&1 "
# run the command
result = zeus.system(cmd, "", flags)
# reload the file in case it was changed by the command
zeus.FileReloadCurrent()
# see if any output was produced
have_errors = check_file_errors(file_errors)
#zeus.message_box(0, cmd, result)
# see if there where any errors runninf the command
if (result != 0) or (have_errors != 0):
# see if we have and error files
if have_errors:
# open the error file in compiler output window
zeus.file_open_compiler(file_errors, cmd, file_name)
else:
# make sure the user will see the error
if zeus.is_debug_enabled() == 0:
zeus.debug_enable()
# log the command to the debug window
zeus.debug_output(cmd + "\n\n" + "Error executing the 'Go Plus' script!\n")
# set capture flags
flags = 1+32+2+4
# run the format again but this time capture the error output
zeus.system(cmd, "", flags)
# we have errors
result = 1;
# on success we return zero
return result
goplus_trigger() # run the macro