From 52126982513675c51d3df5071bc5abae8b67e2fe Mon Sep 17 00:00:00 2001 From: brettlangdon Date: Wed, 21 May 2014 09:21:07 -0400 Subject: [PATCH] add go-mode --- emacs.d/elpa/go-mode-20131222/go-mode-pkg.elc | Bin 0 -> 495 bytes emacs.d/elpa/go-mode-20131222/go-mode.el | 1166 +++++++++++++++++ emacs.d/elpa/go-mode-20131222/go-mode.elc | Bin 0 -> 43921 bytes 3 files changed, 1166 insertions(+) create mode 100644 emacs.d/elpa/go-mode-20131222/go-mode-pkg.elc create mode 100644 emacs.d/elpa/go-mode-20131222/go-mode.el create mode 100644 emacs.d/elpa/go-mode-20131222/go-mode.elc diff --git a/emacs.d/elpa/go-mode-20131222/go-mode-pkg.elc b/emacs.d/elpa/go-mode-20131222/go-mode-pkg.elc new file mode 100644 index 0000000000000000000000000000000000000000..e9a10d30ba3cfa0ef82d0318f915f1d3194017eb GIT binary patch literal 495 zcmbtQ!Ait15Z!Zs!0V$Yg>BhpU2y41$|4JT(jOR;w2da2lB9}$z1b>)c-%S7%zM1| zX4=Djcd=TnineXhv73z5Y8i~j!I6x3(;*u65ZCp#-fik;f!|FULDqt&WSse=lsU03 z7Vv2_5q*}z9Cd{H@Z^kyVi{8~eu(RghL}J~X@y^_W?zf_KMloM!*haUpD2^()K@oo z regexp delimiters directly; use +;; go--regexp-enclose-in-symbol +;; +;; - The character `_` must not be a symbol constituent but a +;; character constituent +;; +;; - Do not use process-lines +;; +;; - Use go--old-completion-list-style when using a plain list as the +;; collection for completing-read +;; +;; - Use go--kill-whole-line instead of kill-whole-line (called +;; kill-entire-line in XEmacs) +;; +;; - Use go--position-bytes instead of position-bytes +(defmacro go--xemacs-p () + `(featurep 'xemacs)) + +(defalias 'go--kill-whole-line + (if (fboundp 'kill-whole-line) + #'kill-whole-line + #'kill-entire-line)) + +;; Delete the current line without putting it in the kill-ring. +(defun go--delete-whole-line (&optional arg) + ;; Emacs uses both kill-region and kill-new, Xemacs only uses + ;; kill-region. In both cases we turn them into operations that do + ;; not modify the kill ring. This solution does depend on the + ;; implementation of kill-line, but it's the only viable solution + ;; that does not require to write kill-line from scratch. + (flet ((kill-region (beg end) + (delete-region beg end)) + (kill-new (s) ())) + (go--kill-whole-line arg))) + +;; declare-function is an empty macro that only byte-compile cares +;; about. Wrap in always false if to satisfy Emacsen without that +;; macro. +(if nil + (declare-function go--position-bytes "go-mode" (point))) + +;; XEmacs unfortunately does not offer position-bytes. We can fall +;; back to just using (point), but it will be incorrect as soon as +;; multibyte characters are being used. +(if (fboundp 'position-bytes) + (defalias 'go--position-bytes #'position-bytes) + (defun go--position-bytes (point) point)) + +(defun go--old-completion-list-style (list) + (mapcar (lambda (x) (cons x nil)) list)) + +;; GNU Emacs 24 has prog-mode, older GNU Emacs and XEmacs do not, so +;; copy its definition for those. +(if (not (fboundp 'prog-mode)) + (define-derived-mode prog-mode fundamental-mode "Prog" + "Major mode for editing source code." + (set (make-local-variable 'require-final-newline) mode-require-final-newline) + (set (make-local-variable 'parse-sexp-ignore-comments) t) + (setq bidi-paragraph-direction 'left-to-right))) + +(defun go--regexp-enclose-in-symbol (s) + ;; XEmacs does not support \_<, GNU Emacs does. In GNU Emacs we make + ;; extensive use of \_< to support unicode in identifiers. Until we + ;; come up with a better solution for XEmacs, this solution will + ;; break fontification in XEmacs for identifiers such as "typeľ". + ;; XEmacs will consider "type" a keyword, GNU Emacs won't. + + (if (go--xemacs-p) + (concat "\\<" s "\\>") + (concat "\\_<" s "\\_>"))) + +;; Move up one level of parentheses. +(defun go-goto-opening-parenthesis (&optional legacy-unused) + ;; The old implementation of go-goto-opening-parenthesis had an + ;; optional argument to speed up the function. It didn't change the + ;; function's outcome. + + ;; Silently fail if there's no matching opening parenthesis. + (condition-case nil + (backward-up-list) + (scan-error nil))) + + +(defconst go-dangling-operators-regexp "[^-]-\\|[^+]\\+\\|[/*&><.=|^]") +(defconst go-identifier-regexp "[[:word:][:multibyte:]]+") +(defconst go-label-regexp go-identifier-regexp) +(defconst go-type-regexp "[[:word:][:multibyte:]*]+") +(defconst go-func-regexp (concat (go--regexp-enclose-in-symbol "func") "\\s *\\(" go-identifier-regexp "\\)")) +(defconst go-func-meth-regexp (concat + (go--regexp-enclose-in-symbol "func") "\\s *\\(?:(\\s *" + "\\(" go-identifier-regexp "\\s +\\)?" go-type-regexp + "\\s *)\\s *\\)?\\(" + go-identifier-regexp + "\\)(")) +(defconst go-builtins + '("append" "cap" "close" "complex" "copy" + "delete" "imag" "len" "make" "new" + "panic" "print" "println" "real" "recover") + "All built-in functions in the Go language. Used for font locking.") + +(defconst go-mode-keywords + '("break" "default" "func" "interface" "select" + "case" "defer" "go" "map" "struct" + "chan" "else" "goto" "package" "switch" + "const" "fallthrough" "if" "range" "type" + "continue" "for" "import" "return" "var") + "All keywords in the Go language. Used for font locking.") + +(defconst go-constants '("nil" "true" "false" "iota")) +(defconst go-type-name-regexp (concat "\\(?:[*(]\\)*\\(?:" go-identifier-regexp "\\.\\)?\\(" go-identifier-regexp "\\)")) + +(defvar go-dangling-cache) +(defvar go-godoc-history nil) +(defvar go--coverage-current-file-name) + +(defgroup go nil + "Major mode for editing Go code" + :group 'languages) + +(defgroup go-cover nil + "Options specific to `cover`" + :group 'go) + +(defcustom go-fontify-function-calls t + "Fontify function and method calls if this is non-nil." + :type 'boolean + :group 'go) + +(defcustom go-mode-hook nil + "Hook called by `go-mode'." + :type 'hook + :group 'go) + +(defcustom go-command "go" + "The 'go' command. Some users have multiple Go development +trees and invoke the 'go' tool via a wrapper that sets GOROOT and +GOPATH based on the current directory. Such users should +customize this variable to point to the wrapper script." + :type 'string + :group 'go) + +(defcustom gofmt-command "gofmt" + "The 'gofmt' command. Some users may replace this with 'goimports' +from https://github.com/bradfitz/goimports." + :type 'string + :group 'go) + +(defface go-coverage-untracked + '((t (:foreground "#505050"))) + "Coverage color of untracked code." + :group 'go-cover) + +(defface go-coverage-0 + '((t (:foreground "#c00000"))) + "Coverage color for uncovered code." + :group 'go-cover) +(defface go-coverage-1 + '((t (:foreground "#808080"))) + "Coverage color for covered code with weight 1." + :group 'go-cover) +(defface go-coverage-2 + '((t (:foreground "#748c83"))) + "Coverage color for covered code with weight 2." + :group 'go-cover) +(defface go-coverage-3 + '((t (:foreground "#689886"))) + "Coverage color for covered code with weight 3." + :group 'go-cover) +(defface go-coverage-4 + '((t (:foreground "#5ca489"))) + "Coverage color for covered code with weight 4." + :group 'go-cover) +(defface go-coverage-5 + '((t (:foreground "#50b08c"))) + "Coverage color for covered code with weight 5." + :group 'go-cover) +(defface go-coverage-6 + '((t (:foreground "#44bc8f"))) + "Coverage color for covered code with weight 6." + :group 'go-cover) +(defface go-coverage-7 + '((t (:foreground "#38c892"))) + "Coverage color for covered code with weight 7." + :group 'go-cover) +(defface go-coverage-8 + '((t (:foreground "#2cd495"))) + "Coverage color for covered code with weight 8. +For mode=set, all covered lines will have this weight." + :group 'go-cover) +(defface go-coverage-9 + '((t (:foreground "#20e098"))) + "Coverage color for covered code with weight 9." + :group 'go-cover) +(defface go-coverage-10 + '((t (:foreground "#14ec9b"))) + "Coverage color for covered code with weight 10." + :group 'go-cover) +(defface go-coverage-covered + '((t (:foreground "#2cd495"))) + "Coverage color of covered code." + :group 'go-cover) + +(defvar go-mode-syntax-table + (let ((st (make-syntax-table))) + (modify-syntax-entry ?+ "." st) + (modify-syntax-entry ?- "." st) + (modify-syntax-entry ?% "." st) + (modify-syntax-entry ?& "." st) + (modify-syntax-entry ?| "." st) + (modify-syntax-entry ?^ "." st) + (modify-syntax-entry ?! "." st) + (modify-syntax-entry ?= "." st) + (modify-syntax-entry ?< "." st) + (modify-syntax-entry ?> "." st) + (modify-syntax-entry ?/ (if (go--xemacs-p) ". 1456" ". 124b") st) + (modify-syntax-entry ?* ". 23" st) + (modify-syntax-entry ?\n "> b" st) + (modify-syntax-entry ?\" "\"" st) + (modify-syntax-entry ?\' "\"" st) + (modify-syntax-entry ?` "\"" st) + (modify-syntax-entry ?\\ "\\" st) + ;; It would be nicer to have _ as a symbol constituent, but that + ;; would trip up XEmacs, which does not support the \_< anchor + (modify-syntax-entry ?_ "w" st) + + st) + "Syntax table for Go mode.") + +(defun go--build-font-lock-keywords () + ;; we cannot use 'symbols in regexp-opt because GNU Emacs <24 + ;; doesn't understand that + (append + `((,(go--regexp-enclose-in-symbol (regexp-opt go-mode-keywords t)) . font-lock-keyword-face) + (,(go--regexp-enclose-in-symbol (regexp-opt go-builtins t)) . font-lock-builtin-face) + (,(go--regexp-enclose-in-symbol (regexp-opt go-constants t)) . font-lock-constant-face) + (,go-func-regexp 1 font-lock-function-name-face)) ;; function (not method) name + + (if go-fontify-function-calls + `((,(concat "\\(" go-identifier-regexp "\\)[[:space:]]*(") 1 font-lock-function-name-face) ;; function call/method name + (,(concat "[^[:word:][:multibyte:]](\\(" go-identifier-regexp "\\))[[:space:]]*(") 1 font-lock-function-name-face)) ;; bracketed function call + `((,go-func-meth-regexp 1 font-lock-function-name-face))) ;; method name + + `( + (,(concat (go--regexp-enclose-in-symbol "type") "[[:space:]]*\\([^[:space:]]+\\)") 1 font-lock-type-face) ;; types + (,(concat (go--regexp-enclose-in-symbol "type") "[[:space:]]*" go-identifier-regexp "[[:space:]]*" go-type-name-regexp) 1 font-lock-type-face) ;; types + (,(concat "[^[:word:][:multibyte:]]\\[\\([[:digit:]]+\\|\\.\\.\\.\\)?\\]" go-type-name-regexp) 2 font-lock-type-face) ;; Arrays/slices + (,(concat "\\(" go-identifier-regexp "\\)" "{") 1 font-lock-type-face) + (,(concat (go--regexp-enclose-in-symbol "map") "\\[[^]]+\\]" go-type-name-regexp) 1 font-lock-type-face) ;; map value type + (,(concat (go--regexp-enclose-in-symbol "map") "\\[" go-type-name-regexp) 1 font-lock-type-face) ;; map key type + (,(concat (go--regexp-enclose-in-symbol "chan") "[[:space:]]*\\(?:<-\\)?" go-type-name-regexp) 1 font-lock-type-face) ;; channel type + (,(concat (go--regexp-enclose-in-symbol "\\(?:new\\|make\\)") "\\(?:[[:space:]]\\|)\\)*(" go-type-name-regexp) 1 font-lock-type-face) ;; new/make type + ;; TODO do we actually need this one or isn't it just a function call? + (,(concat "\\.\\s *(" go-type-name-regexp) 1 font-lock-type-face) ;; Type conversion + (,(concat (go--regexp-enclose-in-symbol "func") "[[:space:]]+(" go-identifier-regexp "[[:space:]]+" go-type-name-regexp ")") 1 font-lock-type-face) ;; Method receiver + (,(concat (go--regexp-enclose-in-symbol "func") "[[:space:]]+(" go-type-name-regexp ")") 1 font-lock-type-face) ;; Method receiver without variable name + ;; Like the original go-mode this also marks compound literal + ;; fields. There, it was marked as to fix, but I grew quite + ;; accustomed to it, so it'll stay for now. + (,(concat "^[[:space:]]*\\(" go-label-regexp "\\)[[:space:]]*:\\(\\S.\\|$\\)") 1 font-lock-constant-face) ;; Labels and compound literal fields + (,(concat (go--regexp-enclose-in-symbol "\\(goto\\|break\\|continue\\)") "[[:space:]]*\\(" go-label-regexp "\\)") 2 font-lock-constant-face)))) ;; labels in goto/break/continue + +(defvar go-mode-map + (let ((m (make-sparse-keymap))) + (define-key m "}" #'go-mode-insert-and-indent) + (define-key m ")" #'go-mode-insert-and-indent) + (define-key m "," #'go-mode-insert-and-indent) + (define-key m ":" #'go-mode-insert-and-indent) + (define-key m "=" #'go-mode-insert-and-indent) + (define-key m (kbd "C-c C-a") #'go-import-add) + (define-key m (kbd "C-c C-j") #'godef-jump) + (define-key m (kbd "C-x 4 C-c C-j") #'godef-jump-other-window) + (define-key m (kbd "C-c C-d") #'godef-describe) + m) + "Keymap used by Go mode to implement electric keys.") + +(defun go-mode-insert-and-indent (key) + "Invoke the global binding of KEY, then reindent the line." + + (interactive (list (this-command-keys))) + (call-interactively (lookup-key (current-global-map) key)) + (indent-according-to-mode)) + +(defmacro go-paren-level () + `(car (syntax-ppss))) + +(defmacro go-in-string-or-comment-p () + `(nth 8 (syntax-ppss))) + +(defmacro go-in-string-p () + `(nth 3 (syntax-ppss))) + +(defmacro go-in-comment-p () + `(nth 4 (syntax-ppss))) + +(defmacro go-goto-beginning-of-string-or-comment () + `(goto-char (nth 8 (syntax-ppss)))) + +(defun go--backward-irrelevant (&optional stop-at-string) + "Skips backwards over any characters that are irrelevant for +indentation and related tasks. + +It skips over whitespace, comments, cases and labels and, if +STOP-AT-STRING is not true, over strings." + + (let (pos (start-pos (point))) + (skip-chars-backward "\n\s\t") + (if (and (save-excursion (beginning-of-line) (go-in-string-p)) (looking-back "`") (not stop-at-string)) + (backward-char)) + (if (and (go-in-string-p) (not stop-at-string)) + (go-goto-beginning-of-string-or-comment)) + (if (looking-back "\\*/") + (backward-char)) + (if (go-in-comment-p) + (go-goto-beginning-of-string-or-comment)) + (setq pos (point)) + (beginning-of-line) + (if (or (looking-at (concat "^" go-label-regexp ":")) (looking-at "^[[:space:]]*\\(case .+\\|default\\):")) + (end-of-line 0) + (goto-char pos)) + (if (/= start-pos (point)) + (go--backward-irrelevant stop-at-string)) + (/= start-pos (point)))) + +(defun go--buffer-narrowed-p () + "Return non-nil if the current buffer is narrowed." + (/= (buffer-size) + (- (point-max) + (point-min)))) + +(defun go-previous-line-has-dangling-op-p () + "Returns non-nil if the current line is a continuation line." + (let* ((cur-line (line-number-at-pos)) + (val (gethash cur-line go-dangling-cache 'nope))) + (if (or (go--buffer-narrowed-p) (equal val 'nope)) + (save-excursion + (beginning-of-line) + (go--backward-irrelevant t) + (setq val (looking-back go-dangling-operators-regexp)) + (if (not (go--buffer-narrowed-p)) + (puthash cur-line val go-dangling-cache)))) + val)) + +(defun go--at-function-definition () + "Return non-nil if point is on the opening curly brace of a +function definition. + +We do this by first calling (beginning-of-defun), which will take +us to the start of *some* function. We then look for the opening +curly brace of that function and compare its position against the +curly brace we are checking. If they match, we return non-nil." + (if (= (char-after) ?\{) + (save-excursion + (let ((old-point (point)) + start-nesting) + (beginning-of-defun) + (when (looking-at "func ") + (setq start-nesting (go-paren-level)) + (skip-chars-forward "^{") + (while (> (go-paren-level) start-nesting) + (forward-char) + (skip-chars-forward "^{") 0) + (if (and (= (go-paren-level) start-nesting) (= old-point (point))) + t)))))) + +(defun go--indentation-for-opening-parenthesis () + "Return the semantic indentation for the current opening parenthesis. + +If point is on an opening curly brace and said curly brace +belongs to a function declaration, the indentation of the func +keyword will be returned. Otherwise the indentation of the +current line will be returned." + (save-excursion + (if (go--at-function-definition) + (progn + (beginning-of-defun) + (current-indentation)) + (current-indentation)))) + +(defun go-indentation-at-point () + (save-excursion + (let (start-nesting) + (back-to-indentation) + (setq start-nesting (go-paren-level)) + + (cond + ((go-in-string-p) + (current-indentation)) + ((looking-at "[])}]") + (go-goto-opening-parenthesis) + (if (go-previous-line-has-dangling-op-p) + (- (current-indentation) tab-width) + (go--indentation-for-opening-parenthesis))) + ((progn (go--backward-irrelevant t) (looking-back go-dangling-operators-regexp)) + ;; only one nesting for all dangling operators in one operation + (if (go-previous-line-has-dangling-op-p) + (current-indentation) + (+ (current-indentation) tab-width))) + ((zerop (go-paren-level)) + 0) + ((progn (go-goto-opening-parenthesis) (< (go-paren-level) start-nesting)) + (if (go-previous-line-has-dangling-op-p) + (current-indentation) + (+ (go--indentation-for-opening-parenthesis) tab-width))) + (t + (current-indentation)))))) + +(defun go-mode-indent-line () + (interactive) + (let (indent + shift-amt + (pos (- (point-max) (point))) + (point (point)) + (beg (line-beginning-position))) + (back-to-indentation) + (if (go-in-string-or-comment-p) + (goto-char point) + (setq indent (go-indentation-at-point)) + (if (looking-at (concat go-label-regexp ":\\([[:space:]]*/.+\\)?$\\|case .+:\\|default:")) + (decf indent tab-width)) + (setq shift-amt (- indent (current-column))) + (if (zerop shift-amt) + nil + (delete-region beg (point)) + (indent-to indent)) + ;; If initial point was within line's indentation, + ;; position after the indentation. Else stay at same point in text. + (if (> (- (point-max) pos) (point)) + (goto-char (- (point-max) pos)))))) + +(defun go-beginning-of-defun (&optional count) + (setq count (or count 1)) + (let ((first t) + failure) + (dotimes (i (abs count)) + (while (and (not failure) + (or first (go-in-string-or-comment-p))) + (if (>= count 0) + (progn + (go--backward-irrelevant) + (if (not (re-search-backward go-func-meth-regexp nil t)) + (setq failure t))) + (if (looking-at go-func-meth-regexp) + (forward-char)) + (if (not (re-search-forward go-func-meth-regexp nil t)) + (setq failure t))) + (setq first nil))) + (if (< count 0) + (beginning-of-line)) + (not failure))) + +(defun go-end-of-defun () + (let (orig-level) + ;; It can happen that we're not placed before a function by emacs + (if (not (looking-at "func")) + (go-beginning-of-defun -1)) + (skip-chars-forward "^{") + (forward-char) + (setq orig-level (go-paren-level)) + (while (>= (go-paren-level) orig-level) + (skip-chars-forward "^}") + (forward-char)))) + +;;;###autoload +(define-derived-mode go-mode prog-mode "Go" + "Major mode for editing Go source text. + +This mode provides (not just) basic editing capabilities for +working with Go code. It offers almost complete syntax +highlighting, indentation that is almost identical to gofmt and +proper parsing of the buffer content to allow features such as +navigation by function, manipulation of comments or detection of +strings. + +In addition to these core features, it offers various features to +help with writing Go code. You can directly run buffer content +through gofmt, read godoc documentation from within Emacs, modify +and clean up the list of package imports or interact with the +Playground (uploading and downloading pastes). + +The following extra functions are defined: + +- `gofmt' +- `godoc' +- `go-import-add' +- `go-remove-unused-imports' +- `go-goto-imports' +- `go-play-buffer' and `go-play-region' +- `go-download-play' +- `godef-describe' and `godef-jump' +- `go-coverage' + +If you want to automatically run `gofmt' before saving a file, +add the following hook to your emacs configuration: + +\(add-hook 'before-save-hook #'gofmt-before-save) + +If you want to use `godef-jump' instead of etags (or similar), +consider binding godef-jump to `M-.', which is the default key +for `find-tag': + +\(add-hook 'go-mode-hook (lambda () + (local-set-key (kbd \"M-.\") #'godef-jump))) + +Please note that godef is an external dependency. You can install +it with + +go get code.google.com/p/rog-go/exp/cmd/godef + + +If you're looking for even more integration with Go, namely +on-the-fly syntax checking, auto-completion and snippets, it is +recommended that you look at goflymake +\(https://github.com/dougm/goflymake), gocode +\(https://github.com/nsf/gocode), go-eldoc +\(github.com/syohex/emacs-go-eldoc) and yasnippet-go +\(https://github.com/dominikh/yasnippet-go)" + + ;; Font lock + (set (make-local-variable 'font-lock-defaults) + '(go--build-font-lock-keywords)) + + ;; Indentation + (set (make-local-variable 'indent-line-function) #'go-mode-indent-line) + + ;; Comments + (set (make-local-variable 'comment-start) "// ") + (set (make-local-variable 'comment-end) "") + (set (make-local-variable 'comment-use-syntax) t) + (set (make-local-variable 'comment-start-skip) "\\(//+\\|/\\*+\\)\\s *") + + (set (make-local-variable 'beginning-of-defun-function) #'go-beginning-of-defun) + (set (make-local-variable 'end-of-defun-function) #'go-end-of-defun) + + (set (make-local-variable 'parse-sexp-lookup-properties) t) + (if (boundp 'syntax-propertize-function) + (set (make-local-variable 'syntax-propertize-function) #'go-propertize-syntax)) + + (set (make-local-variable 'go-dangling-cache) (make-hash-table :test 'eql)) + (add-hook 'before-change-functions (lambda (x y) (setq go-dangling-cache (make-hash-table :test 'eql))) t t) + + + (setq imenu-generic-expression + '(("type" "^type *\\([^ \t\n\r\f]*\\)" 1) + ("func" "^func *\\(.*\\) {" 1))) + (imenu-add-to-menubar "Index") + + ;; Go style + (setq indent-tabs-mode t) + + ;; Handle unit test failure output in compilation-mode + ;; + ;; Note the final t argument to add-to-list for append, ie put these at the + ;; *ends* of compilation-error-regexp-alist[-alist]. We want go-test to be + ;; handled first, otherwise other elements will match that don't work, and + ;; those alists are traversed in *reverse* order: + ;; http://lists.gnu.org/archive/html/bug-gnu-emacs/2001-12/msg00674.html + (when (and (boundp 'compilation-error-regexp-alist) + (boundp 'compilation-error-regexp-alist-alist)) + (add-to-list 'compilation-error-regexp-alist 'go-test t) + (add-to-list 'compilation-error-regexp-alist-alist + '(go-test . ("^\t+\\([^()\t\n]+\\):\\([0-9]+\\):? .*$" 1 2)) t))) + +;;;###autoload +(add-to-list 'auto-mode-alist (cons "\\.go\\'" 'go-mode)) + +(defun go--apply-rcs-patch (patch-buffer) + "Apply an RCS-formatted diff from PATCH-BUFFER to the current +buffer." + (let ((target-buffer (current-buffer)) + ;; Relative offset between buffer line numbers and line numbers + ;; in patch. + ;; + ;; Line numbers in the patch are based on the source file, so + ;; we have to keep an offset when making changes to the + ;; buffer. + ;; + ;; Appending lines decrements the offset (possibly making it + ;; negative), deleting lines increments it. This order + ;; simplifies the forward-line invocations. + (line-offset 0)) + (save-excursion + (with-current-buffer patch-buffer + (goto-char (point-min)) + (while (not (eobp)) + (unless (looking-at "^\\([ad]\\)\\([0-9]+\\) \\([0-9]+\\)") + (error "invalid rcs patch or internal error in go--apply-rcs-patch")) + (forward-line) + (let ((action (match-string 1)) + (from (string-to-number (match-string 2))) + (len (string-to-number (match-string 3)))) + (cond + ((equal action "a") + (let ((start (point))) + (forward-line len) + (let ((text (buffer-substring start (point)))) + (with-current-buffer target-buffer + (decf line-offset len) + (goto-char (point-min)) + (forward-line (- from len line-offset)) + (insert text))))) + ((equal action "d") + (with-current-buffer target-buffer + (go--goto-line (- from line-offset)) + (incf line-offset len) + (go--delete-whole-line len))) + (t + (error "invalid rcs patch or internal error in go--apply-rcs-patch"))))))))) + +(defun gofmt () + "Formats the current buffer according to the gofmt tool." + + (interactive) + (let ((tmpfile (make-temp-file "gofmt" nil ".go")) + (patchbuf (get-buffer-create "*Gofmt patch*")) + (errbuf (get-buffer-create "*Gofmt Errors*")) + (coding-system-for-read 'utf-8) + (coding-system-for-write 'utf-8)) + + (with-current-buffer errbuf + (setq buffer-read-only nil) + (erase-buffer)) + (with-current-buffer patchbuf + (erase-buffer)) + + (write-region nil nil tmpfile) + + ;; We're using errbuf for the mixed stdout and stderr output. This + ;; is not an issue because gofmt -w does not produce any stdout + ;; output in case of success. + (if (zerop (call-process gofmt-command nil errbuf nil "-w" tmpfile)) + (if (zerop (call-process-region (point-min) (point-max) "diff" nil patchbuf nil "-n" "-" tmpfile)) + (progn + (kill-buffer errbuf) + (message "Buffer is already gofmted")) + (go--apply-rcs-patch patchbuf) + (kill-buffer errbuf) + (message "Applied gofmt")) + (message "Could not apply gofmt. Check errors for details") + (gofmt--process-errors (buffer-file-name) tmpfile errbuf)) + + (kill-buffer patchbuf) + (delete-file tmpfile))) + + +(defun gofmt--process-errors (filename tmpfile errbuf) + ;; Convert the gofmt stderr to something understood by the compilation mode. + (with-current-buffer errbuf + (goto-char (point-min)) + (insert "gofmt errors:\n") + (while (search-forward-regexp (concat "^\\(" (regexp-quote tmpfile) "\\):") nil t) + (replace-match (file-name-nondirectory filename) t t nil 1)) + (compilation-mode) + (display-buffer errbuf))) + +;;;###autoload +(defun gofmt-before-save () + "Add this to .emacs to run gofmt on the current buffer when saving: + (add-hook 'before-save-hook 'gofmt-before-save). + +Note that this will cause go-mode to get loaded the first time +you save any file, kind of defeating the point of autoloading." + + (interactive) + (when (eq major-mode 'go-mode) (gofmt))) + +(defun godoc--read-query () + "Read a godoc query from the minibuffer." + ;; Compute the default query as the symbol under the cursor. + ;; TODO: This does the wrong thing for e.g. multipart.NewReader (it only grabs + ;; half) but I see no way to disambiguate that from e.g. foobar.SomeMethod. + (let* ((bounds (bounds-of-thing-at-point 'symbol)) + (symbol (if bounds + (buffer-substring-no-properties (car bounds) + (cdr bounds))))) + (completing-read (if symbol + (format "godoc (default %s): " symbol) + "godoc: ") + (go--old-completion-list-style (go-packages)) nil nil nil 'go-godoc-history symbol))) + +(defun godoc--get-buffer (query) + "Get an empty buffer for a godoc query." + (let* ((buffer-name (concat "*godoc " query "*")) + (buffer (get-buffer buffer-name))) + ;; Kill the existing buffer if it already exists. + (when buffer (kill-buffer buffer)) + (get-buffer-create buffer-name))) + +(defun godoc--buffer-sentinel (proc event) + "Sentinel function run when godoc command completes." + (with-current-buffer (process-buffer proc) + (cond ((string= event "finished\n") ;; Successful exit. + (goto-char (point-min)) + (view-mode 1) + (display-buffer (current-buffer) t)) + ((/= (process-exit-status proc) 0) ;; Error exit. + (let ((output (buffer-string))) + (kill-buffer (current-buffer)) + (message (concat "godoc: " output))))))) + +;;;###autoload +(defun godoc (query) + "Show go documentation for a query, much like M-x man." + (interactive (list (godoc--read-query))) + (unless (string= query "") + (set-process-sentinel + (start-process-shell-command "godoc" (godoc--get-buffer query) + (concat "godoc " query)) + 'godoc--buffer-sentinel) + nil)) + +(defun go-goto-imports () + "Move point to the block of imports. + +If using + + import ( + \"foo\" + \"bar\" + ) + +it will move point directly behind the last import. + +If using + + import \"foo\" + import \"bar\" + +it will move point to the next line after the last import. + +If no imports can be found, point will be moved after the package +declaration." + (interactive) + ;; FIXME if there's a block-commented import before the real + ;; imports, we'll jump to that one. + + ;; Generally, this function isn't very forgiving. it'll bark on + ;; extra whitespace. It works well for clean code. + (let ((old-point (point))) + (goto-char (point-min)) + (cond + ((re-search-forward "^import ()" nil t) + (backward-char 1) + 'block-empty) + ((re-search-forward "^import ([^)]+)" nil t) + (backward-char 2) + 'block) + ((re-search-forward "\\(^import \\([^\"]+ \\)?\"[^\"]+\"\n?\\)+" nil t) + 'single) + ((re-search-forward "^[[:space:]\n]*package .+?\n" nil t) + (message "No imports found, moving point after package declaration") + 'none) + (t + (goto-char old-point) + (message "No imports or package declaration found. Is this really a Go file?") + 'fail)))) + +(defun go-play-buffer () + "Like `go-play-region', but acts on the entire buffer." + (interactive) + (go-play-region (point-min) (point-max))) + +(defun go-play-region (start end) + "Send the region to the Playground and stores the resulting +link in the kill ring." + (interactive "r") + (let* ((url-request-method "POST") + (url-request-extra-headers + '(("Content-Type" . "application/x-www-form-urlencoded"))) + (url-request-data + (encode-coding-string + (buffer-substring-no-properties start end) + 'utf-8)) + (content-buf (url-retrieve + "http://play.golang.org/share" + (lambda (arg) + (cond + ((equal :error (car arg)) + (signal 'go-play-error (cdr arg))) + (t + (re-search-forward "\n\n") + (kill-new (format "http://play.golang.org/p/%s" (buffer-substring (point) (point-max)))) + (message "http://play.golang.org/p/%s" (buffer-substring (point) (point-max))))))))))) + +;;;###autoload +(defun go-download-play (url) + "Downloads a paste from the playground and inserts it in a Go +buffer. Tries to look for a URL at point." + (interactive (list (read-from-minibuffer "Playground URL: " (ffap-url-p (ffap-string-at-point 'url))))) + (with-current-buffer + (let ((url-request-method "GET") url-request-data url-request-extra-headers) + (url-retrieve-synchronously (concat url ".go"))) + (let ((buffer (generate-new-buffer (concat (car (last (split-string url "/"))) ".go")))) + (goto-char (point-min)) + (re-search-forward "\n\n") + (copy-to-buffer buffer (point) (point-max)) + (kill-buffer) + (with-current-buffer buffer + (go-mode) + (switch-to-buffer buffer))))) + +(defun go-propertize-syntax (start end) + (save-excursion + (goto-char start) + (while (search-forward "\\" end t) + (put-text-property (1- (point)) (point) 'syntax-table (if (= (char-after) ?`) '(1) '(9)))))) + +(defun go-import-add (arg import) + "Add a new import to the list of imports. + +When called with a prefix argument asks for an alternative name +to import the package as. + +If no list exists yet, one will be created if possible. + +If an identical import has been commented, it will be +uncommented, otherwise a new import will be added." + + ;; - If there's a matching `// import "foo"`, uncomment it + ;; - If we're in an import() block and there's a matching `"foo"`, uncomment it + ;; - Otherwise add a new import, with the appropriate syntax + (interactive + (list + current-prefix-arg + (replace-regexp-in-string "^[\"']\\|[\"']$" "" (completing-read "Package: " (go--old-completion-list-style (go-packages)))))) + (save-excursion + (let (as line import-start) + (if arg + (setq as (read-from-minibuffer "Import as: "))) + (if as + (setq line (format "%s \"%s\"" as import)) + (setq line (format "\"%s\"" import))) + + (goto-char (point-min)) + (if (re-search-forward (concat "^[[:space:]]*//[[:space:]]*import " line "$") nil t) + (uncomment-region (line-beginning-position) (line-end-position)) + (case (go-goto-imports) + ('fail (message "Could not find a place to add import.")) + ('block-empty + (insert "\n\t" line "\n")) + ('block + (save-excursion + (re-search-backward "^import (") + (setq import-start (point))) + (if (re-search-backward (concat "^[[:space:]]*//[[:space:]]*" line "$") import-start t) + (uncomment-region (line-beginning-position) (line-end-position)) + (insert "\n\t" line))) + ('single (insert "import " line "\n")) + ('none (insert "\nimport (\n\t" line "\n)\n"))))))) + +(defun go-root-and-paths () + (let* ((output (split-string (shell-command-to-string (concat go-command " env GOROOT GOPATH")) + "\n")) + (root (car output)) + (paths (split-string (cadr output) ":"))) + (append (list root) paths))) + +(defun go--string-prefix-p (s1 s2 &optional ignore-case) + "Return non-nil if S1 is a prefix of S2. +If IGNORE-CASE is non-nil, the comparison is case-insensitive." + (eq t (compare-strings s1 nil nil + s2 0 (length s1) ignore-case))) + +(defun go--directory-dirs (dir) + "Recursively return all subdirectories in DIR." + (if (file-directory-p dir) + (let ((dir (directory-file-name dir)) + (dirs '()) + (files (directory-files dir nil nil t))) + (dolist (file files) + (unless (member file '("." "..")) + (let ((file (concat dir "/" file))) + (if (file-directory-p file) + (setq dirs (append (cons file + (go--directory-dirs file)) + dirs)))))) + dirs) + '())) + + +(defun go-packages () + (sort + (delete-dups + (mapcan + (lambda (topdir) + (let ((pkgdir (concat topdir "/pkg/"))) + (mapcan (lambda (dir) + (mapcar (lambda (file) + (let ((sub (substring file (length pkgdir) -2))) + (unless (or (go--string-prefix-p "obj/" sub) (go--string-prefix-p "tool/" sub)) + (mapconcat #'identity (cdr (split-string sub "/")) "/")))) + (if (file-directory-p dir) + (directory-files dir t "\\.a$")))) + (if (file-directory-p pkgdir) + (go--directory-dirs pkgdir))))) + (go-root-and-paths))) + #'string<)) + +(defun go-unused-imports-lines () + ;; FIXME Technically, -o /dev/null fails in quite some cases (on + ;; Windows, when compiling from within GOPATH). Practically, + ;; however, it has the same end result: There won't be a + ;; compiled binary/archive, and we'll get our import errors when + ;; there are any. + (reverse (remove nil + (mapcar + (lambda (line) + (if (string-match "^\\(.+\\):\\([[:digit:]]+\\): imported and not used: \".+\".*$" line) + (if (string= (file-truename (match-string 1 line)) (file-truename buffer-file-name)) + (string-to-number (match-string 2 line))))) + (split-string (shell-command-to-string + (concat go-command + (if (string-match "_test\.go$" buffer-file-truename) + " test -c" + " build -o /dev/null"))) "\n"))))) + +(defun go-remove-unused-imports (arg) + "Removes all unused imports. If ARG is non-nil, unused imports +will be commented, otherwise they will be removed completely." + (interactive "P") + (save-excursion + (let ((cur-buffer (current-buffer)) flymake-state lines) + (when (boundp 'flymake-mode) + (setq flymake-state flymake-mode) + (flymake-mode-off)) + (save-some-buffers nil (lambda () (equal cur-buffer (current-buffer)))) + (if (buffer-modified-p) + (message "Cannot operate on unsaved buffer") + (setq lines (go-unused-imports-lines)) + (dolist (import lines) + (go--goto-line import) + (beginning-of-line) + (if arg + (comment-region (line-beginning-position) (line-end-position)) + (go--delete-whole-line))) + (message "Removed %d imports" (length lines))) + (if flymake-state (flymake-mode-on))))) + +(defun godef--find-file-line-column (specifier other-window) + "Given a file name in the format of `filename:line:column', +visit FILENAME and go to line LINE and column COLUMN." + (if (not (string-match "\\(.+\\):\\([0-9]+\\):\\([0-9]+\\)" specifier)) + ;; We've only been given a directory name + (funcall (if other-window #'find-file-other-window #'find-file) specifier) + (let ((filename (match-string 1 specifier)) + (line (string-to-number (match-string 2 specifier))) + (column (string-to-number (match-string 3 specifier)))) + (with-current-buffer (funcall (if other-window #'find-file-other-window #'find-file) filename) + (go--goto-line line) + (beginning-of-line) + (forward-char (1- column)) + (if (buffer-modified-p) + (message "Buffer is modified, file position might not have been correct")))))) + +(defun godef--call (point) + "Call godef, acquiring definition position and expression +description at POINT." + (if (go--xemacs-p) + (error "godef does not reliably work in XEmacs, expect bad results")) + (if (not (buffer-file-name (go--coverage-origin-buffer))) + (error "Cannot use godef on a buffer without a file name") + (let ((outbuf (get-buffer-create "*godef*"))) + (with-current-buffer outbuf + (erase-buffer)) + (call-process-region (point-min) + (point-max) + "godef" + nil + outbuf + nil + "-i" + "-t" + "-f" + (file-truename (buffer-file-name (go--coverage-origin-buffer))) + "-o" + (number-to-string (go--position-bytes (point)))) + (with-current-buffer outbuf + (split-string (buffer-substring-no-properties (point-min) (point-max)) "\n"))))) + +(defun godef-describe (point) + "Describe the expression at POINT." + (interactive "d") + (condition-case nil + (let ((description (cdr (butlast (godef--call point) 1)))) + (if (not description) + (message "No description found for expression at point") + (message "%s" (mapconcat #'identity description "\n")))) + (file-error (message "Could not run godef binary")))) + +(defun godef-jump (point &optional other-window) + "Jump to the definition of the expression at POINT." + (interactive "d") + (condition-case nil + (let ((file (car (godef--call point)))) + (cond + ((string= "-" file) + (message "godef: expression is not defined anywhere")) + ((string= "godef: no identifier found" file) + (message "%s" file)) + ((go--string-prefix-p "godef: no declaration found for " file) + (message "%s" file)) + ((go--string-prefix-p "error finding import path for " file) + (message "%s" file)) + (t + (push-mark) + (ring-insert find-tag-marker-ring (point-marker)) + (godef--find-file-line-column file other-window)))) + (file-error (message "Could not run godef binary")))) + +(defun godef-jump-other-window (point) + (interactive "d") + (godef-jump point t)) + +(defun go--goto-line (line) + (goto-char (point-min)) + (forward-line (1- line))) + +(defun go--line-column-to-point (line column) + (save-excursion + (go--goto-line line) + (forward-char (1- column)) + (point))) + +(defstruct go--covered + start-line start-column end-line end-column covered count) + +(defun go--coverage-file () + "Return the coverage file to use, either by reading it from the +current coverage buffer or by prompting for it." + (if (boundp 'go--coverage-current-file-name) + go--coverage-current-file-name + (read-file-name "Coverage file: " nil nil t))) + +(defun go--coverage-origin-buffer () + "Return the buffer to base the coverage on." + (or (buffer-base-buffer) (current-buffer))) + +(defun go--coverage-face (count divisor) + "Return the intensity face for COUNT when using DIVISOR +to scale it to a range [0,10]. + +DIVISOR scales the absolute cover count to values from 0 to 10. +For DIVISOR = 0 the count will always translate to 8." + (let* ((norm (cond + ((= count 0) + -0.1) ;; Uncovered code, set to -0.1 so n becomes 0. + ((= divisor 0) + 0.8) ;; covermode=set, set to 0.8 so n becomes 8. + (t + (/ (log count) divisor)))) + (n (1+ (floor (* norm 9))))) ;; Convert normalized count [0,1] to intensity [0,10] + (concat "go-coverage-" (number-to-string n)))) + +(defun go--coverage-make-overlay (range divisor) + "Create a coverage overlay for a RANGE of covered/uncovered +code. Uses DIVISOR to scale absolute counts to a [0,10] scale." + (let* ((count (go--covered-count range)) + (face (go--coverage-face count divisor)) + (ov (make-overlay (go--line-column-to-point (go--covered-start-line range) + (go--covered-start-column range)) + (go--line-column-to-point (go--covered-end-line range) + (go--covered-end-column range))))) + + (overlay-put ov 'face face) + (overlay-put ov 'help-echo (format "Count: %d" count)))) + +(defun go--coverage-clear-overlays () + "Remove existing overlays and put a single untracked overlay +over the entire buffer." + (remove-overlays) + (overlay-put (make-overlay (point-min) (point-max)) + 'face + 'go-coverage-untracked)) + +(defun go--coverage-parse-file (coverage-file file-name) + "Parse COVERAGE-FILE and extract coverage information and +divisor for FILE-NAME." + (let (ranges + (max-count 0)) + (with-temp-buffer + (insert-file-contents coverage-file) + (go--goto-line 2) ;; Skip over mode + (while (not (eobp)) + (let* ((parts (split-string (buffer-substring (point-at-bol) (point-at-eol)) ":")) + (file (car parts)) + (rest (split-string (nth 1 parts) "[., ]"))) + + (destructuring-bind + (start-line start-column end-line end-column num count) + (mapcar #'string-to-number rest) + + (when (string= (file-name-nondirectory file) file-name) + (if (> count max-count) + (setq max-count count)) + (push (make-go--covered :start-line start-line + :start-column start-column + :end-line end-line + :end-column end-column + :covered (/= count 0) + :count count) + ranges))) + + (forward-line))) + + (list ranges (if (> max-count 0) (log max-count) 0))))) + +(defun go-coverage (&optional coverage-file) + "Open a clone of the current buffer and overlay it with +coverage information gathered via go test -coverprofile=COVERAGE-FILE. + +If COVERAGE-FILE is nil, it will either be inferred from the +current buffer if it's already a coverage buffer, or be prompted +for." + (interactive) + (let* ((cur-buffer (current-buffer)) + (origin-buffer (go--coverage-origin-buffer)) + (gocov-buffer-name (concat (buffer-name origin-buffer) "")) + (coverage-file (or coverage-file (go--coverage-file))) + (ranges-and-divisor (go--coverage-parse-file + coverage-file + (file-name-nondirectory (buffer-file-name origin-buffer)))) + (cov-mtime (nth 5 (file-attributes coverage-file))) + (cur-mtime (nth 5 (file-attributes (buffer-file-name origin-buffer))))) + + (if (< (float-time cov-mtime) (float-time cur-mtime)) + (message "Coverage file is older than the source file.")) + + (with-current-buffer (or (get-buffer gocov-buffer-name) + (make-indirect-buffer origin-buffer gocov-buffer-name t)) + (set (make-local-variable 'go--coverage-current-file-name) coverage-file) + + (save-excursion + (go--coverage-clear-overlays) + (dolist (range (car ranges-and-divisor)) + (go--coverage-make-overlay range (cadr ranges-and-divisor)))) + + (if (not (eq cur-buffer (current-buffer))) + (display-buffer (current-buffer) #'display-buffer-reuse-window))))) + +(provide 'go-mode) + +;;; go-mode.el ends here diff --git a/emacs.d/elpa/go-mode-20131222/go-mode.elc b/emacs.d/elpa/go-mode-20131222/go-mode.elc new file mode 100644 index 0000000000000000000000000000000000000000..4e1aa183ec5f4ae08ec67413aae0e94b6311b4cd GIT binary patch literal 43921 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 literal 0 HcmV?d00001