Skip to content

Instantly share code, notes, and snippets.

@hex2010
Last active October 5, 2016 20:08
Show Gist options
  • Save hex2010/5c44616b170817dbf00ae6454ca80bbf to your computer and use it in GitHub Desktop.
Save hex2010/5c44616b170817dbf00ae6454ca80bbf to your computer and use it in GitHub Desktop.
Emacs scripts to work with golang, hard to make it generic thought.
;;; hx-golang.el --- Utils works with Golang
;;; Commentary:
;;; Code:
(defcustom hx-golang-build-flags "-gcflags='-l -N' -tags debug"
"Flags for build golang packages."
:type 'string
:options '(turn-on-auto-fill)
:group 'hx-golang)
(defcustom hx-golang-workspace "hx"
"Subdir in $GOPATH/src which recognize as current workspace."
:type 'string
:options '(turn-on-auto-fill)
:group 'hx-golang)
(defun hx-golang-package-name-of-file (f)
(let ((s (hx-read-file-as-string f)))
(if (string-match "^[ \t]*package[ \t]+\\([_A-Za-z0-9]+\\)[ \t]*$" s)
(match-string 1 s))))
(defun hx-golang--any-go-file (dir)
(car (cl-member-if (lambda (x)
(and (equal (file-name-extension x) "go")
(not (string-suffix-p "_test.go" x))
(not (string-prefix-p "." x))))
(directory-files dir))))
(defun hx-golang-package-name-of-dir (dir)
(let ((gosrc (hx-golang--any-go-file dir)))
(if gosrc (hx-golang-package-name-of-file (concat dir "/" gosrc)))))
;;(go-package-name-of-dir "~/gopath/src/hx/deto" )
(defun hx-golang-package-is-main-p (dir)
(equal (hx-golang-package-name-of-dir dir) "main"))
(defun hx-golang-dir-p (dir)
(and (hx-golang--any-go-file dir) t))
(defun hx-golang-main-packages ()
"List all main package under workspace."
(split-string (shell-command-to-string (format "go list -f '{{.Name}}|{{.ImportPath}}' %s/... | /usr/bin/grep '^main|' | sed 's/^main|\\(..*\\)\\/\\([_A-Za-z0-8\\-]*\\)$/\\1\\/\\2/'" hx-golang-workspace)) "\n" t))
(defvar hx-golang-debug-history nil
"History list for golang debug.")
(defun hx-golang-install-current-package-for-debug ()
(save-some-buffers t)
"Debug模式编译安装当前目录."
(compile (format "go install %s ." hx-golang-build-flags)))
(defun hx-golang-test-current-package ()
(save-some-buffers t)
"go test 当前目录."
(compile "go test ."))
(defun hx-golang--run-main-package (pkgpath dbg)
(let* ((default-directory (concat (getenv "GOPATH") "/src/" pkgpath))
(pkgname (hx-golang-package-name-of-dir default-directory)))
(if (equal pkgname "main")
(let ((cmd (concat (getenv "GOPATH") "/bin/" (file-name-nondirectory pkgpath)))
(buildcmd (format "go install %s %s" hx-golang-build-flags pkgpath))
(buf (format "*Run %s*" (file-name-base pkgpath))))
(save-some-buffers t)
(if (= 0 (call-process-shell-command buildcmd))
(if dbg (dlv (format "dlv exec %s" cmd))
(async-shell-command cmd buf))
(compile buildcmd))) ; compile again to locate issues
(message (concat "Not a main package: " default-directory)))))
(defun hx-golang-prompt-run-package (&optional dbg)
"Prompt and run special main package."
(interactive)
(ivy-read (cond (dbg "Debug: ") (t "Run: "))
(hx-prepositional-dir-name-alist (hx-golang-main-packages))
:action (lambda (x)
(with-ivy-window (hx-golang--run-main-package (cdr x) dbg)))
:require-match t
:caller 'hx-golang-run-current
:history 'hx-golang-debug-history
:preselect (nth 0 hx-golang-debug-history)))
(defun hx-golang-web-export ()
"自动导出workspace下所有web服务端口."
(interactive)
(save-some-buffers t)
(shell-command (format "deto web-export %s/src/%s" (getenv "GOPATH") hx-golang-workspace)))
(provide 'hx-golang)
;;; hx-golang.el ends here
(defun hx-read-file-as-string (f)
(if (file-exists-p f)
(with-temp-buffer (insert-file-contents f)
(buffer-substring-no-properties
(point-min)
(point-max)))))
(defun hx-ingore-buffer (buffer)
"Return whether to ignore BUFFER"
(or (null buffer)
(not (get-buffer-window buffer))
(minibufferp buffer)
(equal " *guide-key*" (buffer-name buffer))))
(defvar hx-buffer-or-window-change-hook nil)
(defvar hx-current-buffer-and-window nil)
(defun hx-current-buffer-and-window ()
"Get current buffer and selected window."
(cons (current-buffer) (frame-selected-window)))
(defun hx--run-buffer-or-window-change-hook ()
"Run hx-buffer-or-window-change-hook on certain condition."
(if (not (hx-ingore-buffer (current-buffer)))
(progn (if (not (equal hx-current-buffer-and-window (hx-current-buffer-and-window)))
(progn
;(message (format "[%s]" (buffer-name (current-buffer))))
(run-hooks 'hx--run-buffer-or-window-change-hook)))
(setq hx-current-buffer-and-window (hx-current-buffer-and-window)))))
(add-hook 'buffer-list-update-hook 'hx--run-buffer-or-window-change-hook)
(defun get-faces (pos)
"Get the font faces at POS."
(remq nil
(list
(get-char-property pos 'read-face-name)
(get-char-property pos 'face)
(plist-get (text-properties-at pos) 'face))))
(defun what-face (pos)
(interactive "d")
(let ((face (get-faces pos)))
(if face (message "Face: %s" face) (message "No face at %d" pos))))
(defun hx-prepositional-file-name (file-name)
"文件基本名前置, 名字在前, 目录在后."
(let* ((base (file-name-nondirectory file-name))
(n (- 20 (string-bytes base))))
(setq n (max 2 n))
(setq base (concat base (make-string n ?\ ) file-name))))
(defun hx-prepositional-dir-name (dir)
(hx-prepositional-file-name (directory-file-name dir)))
(defun hx-prepositional-dir-name-alist (dir-list)
"名字和目录的关联list."
(let (ret)
(dolist (x dir-list ret)
(add-to-list 'ret (cons (hx-prepositional-dir-name x) x) 'APPEND))))
(defun hx-prepositional-file-name-alist (file-list)
"名字和目录的关联list."
(let (ret)
(dolist (x file-list ret)
(add-to-list 'ret (cons (hx-prepositional-file-name x) x) 'APPEND))))
@hex2010
Copy link
Author

hex2010 commented Sep 17, 2016

The main idea for work with golang is hx-golang-debug

work for directory under $GOPATH/src/{workspace}, the {workspace} is default to my workspace "hx"

M-x hx-golang-debug RET will find out all main package under workspace and list out with ivy interface.
select one then auto compile with debug info and install into $GOPATH/bin, then launch gud-dlv to debug it.

The hardest pieces is how to make it fully customizable for example the compile flags for individual package,
support "stand alone" workspace etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment