branch: externals/company commit 75acbc54a46c47a48a061064295cf304d94108a7 Merge: 97cfbc3 e6fa6c0 Author: Dmitry Gutov <dgu...@yandex.ru> Commit: GitHub <nore...@github.com>
Merge pull request #1037 from Ergus/master Fix company-gtags to work with tramp and multiple locations. --- company-gtags.el | 76 ++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/company-gtags.el b/company-gtags.el index 598ba60..86038a3 100644 --- a/company-gtags.el +++ b/company-gtags.el @@ -48,6 +48,7 @@ :package-version '(company . "0.8.1")) (defvar-local company-gtags--tags-available-p 'unknown) +(defvar-local company-gtags--executable 'unknown) (defcustom company-gtags-modes '(prog-mode jde-mode) "Modes that use `company-gtags'. @@ -62,30 +63,57 @@ completion." (locate-dominating-file buffer-file-name "GTAGS")) company-gtags--tags-available-p)) +(defun company-gtags--executable-p () + (cond + ((not (eq company-gtags--executable 'unknown)) ;; the value is already cached + company-gtags--executable) + ((and (version<= "27" emacs-version) ;; can search remotely to set + (file-remote-p default-directory)) + + (with-connection-local-variables + (if (boundp 'company-gtags--executable-connection) + (setq-local company-gtags--executable ;; use if defined as connection-local + company-gtags--executable-connection) + + ;; Else search and set as connection local for next uses. + (setq-local company-gtags--executable (executable-find "global" t)) + (let* ((host (file-remote-p default-directory 'host)) + (symvars (intern (concat host "-vars")))) ;; profile name + + (connection-local-set-profile-variables + symvars + `((company-gtags--executable-connection . ,company-gtags--executable))) + + (connection-local-set-profiles `(:machine ,host) symvars))))) + (t ;; use default value (searched locally) + (setq-local company-gtags--executable company-gtags-executable)))) + (defun company-gtags--fetch-tags (prefix) - (with-temp-buffer - (let (tags) - ;; For some reason Global v 6.6.3 is prone to returning exit status 1 - ;; even on successful searches when '-T' is used. - (when (/= 3 (process-file company-gtags-executable nil - ;; "-T" goes through all the tag files listed in GTAGSLIBPATH - (list (current-buffer) nil) nil "-xGqT" (concat "^" prefix))) - (goto-char (point-min)) - (cl-loop while - (re-search-forward (concat - "^" - "\\([^ ]*\\)" ;; completion - "[ \t]+\\([[:digit:]]+\\)" ;; linum - "[ \t]+\\([^ \t]+\\)" ;; file - "[ \t]+\\(.*\\)" ;; definition - "$" - ) nil t) - collect - (propertize (match-string 1) - 'meta (match-string 4) - 'location (cons (expand-file-name (match-string 3)) - (string-to-number (match-string 2))) - )))))) + "Call global executable " + (let ((caller-buffer (current-buffer))) + (with-temp-buffer + (let ((temp-buffer (current-buffer))) + (when (with-current-buffer caller-buffer + ;; Execute the command in the local buffer but output in the temporal one. + (/= 3 (process-file (company-gtags--executable-p) nil + ;; "-T" goes through all the tag files listed in GTAGSLIBPATH + temp-buffer nil "-xGqT" (concat "^" prefix)))) + (goto-char (point-min)) + (cl-loop while + (re-search-forward (concat + "^" + "\\([^ ]*\\)" ;; completion + "[ \t]+\\([[:digit:]]+\\)" ;; linum + "[ \t]+\\([^ \t]+\\)" ;; file + "[ \t]+\\(.*\\)" ;; definition + "$" + ) nil t) + collect + (propertize (match-string 1) + 'meta (match-string 4) + 'location (cons (expand-file-name (match-string 3)) + (string-to-number (match-string 2))) + ))))))) (defun company-gtags--annotation (arg) (let ((meta (get-text-property 0 'meta arg))) @@ -98,7 +126,7 @@ completion." (interactive (list 'interactive)) (cl-case command (interactive (company-begin-backend 'company-gtags)) - (prefix (and company-gtags-executable + (prefix (and (company-gtags--executable-p) buffer-file-name (apply #'derived-mode-p company-gtags-modes) (not (company-in-string-or-comment))