Coder Social home page Coder Social logo

emacs-counsel-gtags's Introduction

note

GIVEN HOW HARD THIS CODE IS TO MAINTAIN, I'M DEPRECATING IT AND ADVICE YOU LOOK FOR SOMETHING ELSE. PRS ARE STILL WELCOME.

YOU SHOULD CHECKOUT global-tags.el INSTEAD. THIS PACKAGE HAS BETTER MODULARITY, IS DECOUPLED FROM NARROWING FRAMEWORK (IVY, HELM) AND PLENTY OF UNIT TESTS AND INFRASTRUCTURE TO ADD NEW TESTS

counsel-gtags.el melpa badge melpa stable badge Build Status

GNU GLOBAL interface of ivy.

Tasks

  • Basic commands
  • find file command
  • Tag command
  • Context command(dwim)
  • Find definition and references
  • include header support
  • GTAGSLIBPATH support
  • Basic History command
  • History navigate command
  • Tramp support

Requirements

  • Emacs 24.3 or higher versions
  • counsel
  • GNU global 6.2.3 or higher versions

Installation

counsel-gtags is available on MELPA and MELPA stable

You can install counsel-gtags with the following command.

M-x package-install [RET] counsel-gtags [RET]

Basic Usage

You can search for tags or files in the database. Every time you jump to a definition, reference or symbol the current position is pushed to the context stack. You can navigate backward and forward within this stack with counsel-gtags-go-backward and counsel-gtags-go-forward.

counsel-gtags-find-definition

Search for definition.

counsel-gtags-find-reference

Search for references.

counsel-gtags-find-symbol

Search for symbol references.

counsel-gtags-find-file

Search for file among tagged files.

counsel-gtags-go-backward

Go to previous position in context stack.

counsel-gtags-go-forward

Go to next position in context stack.

counsel-gtags-create-tags

Create GNU GLOBAL tags.

counsel-gtags-update-tags

Update tags.

counsel-gtags-dwim

Find name by context.

  • Jump to tag definition if cursor is on tag reference
  • Jump to tag reference if cursor is on tag definition

Other window commands

There are also the commands:

  • counsel-gtags-find-definition-other-window
  • counsel-gtags-find-reference-other-window
  • counsel-gtags-find-symbol-other-window
  • counsel-gtags-find-file-other-window

Similar to the mentioned before with similar names but use other windows instead of the same. This functionality is also available throw ivy-actions in the candidates list pressing M-o j.

Sample Configuration

(add-hook 'c-mode-hook 'counsel-gtags-mode)
(add-hook 'c++-mode-hook 'counsel-gtags-mode)

(with-eval-after-load 'counsel-gtags
  (define-key counsel-gtags-mode-map (kbd "M-t") 'counsel-gtags-find-definition)
  (define-key counsel-gtags-mode-map (kbd "M-r") 'counsel-gtags-find-reference)
  (define-key counsel-gtags-mode-map (kbd "M-s") 'counsel-gtags-find-symbol)
  (define-key counsel-gtags-mode-map (kbd "M-,") 'counsel-gtags-go-backward))

A simpler alternative to the previous configuration is to use the included counsel-gtags-command-map which has all the interactive commands already defined. If you want to use that map you only need to define a prefix for it.

(define-key counsel-gtags-mode-map (kbd ...) #'counsel-gtags-command-map)

Or if you have use-packages and prefer autoloads.

(use-package counsel-gtags
	:bind-keymap ("C-c g" . counsel-gtags-command-map)
	:config
	(counsel-gtags-mode 1))

There are some useful custom variables like

  • counsel-gtags-use-input-at-point: To use thing-at-point functions.

  • counsel-gtags-debug-mode : To enable debug mode which prints some of the commands in the *Messages* buffer.

  • counsel-gtags-use-dynamic-list:

    When this option is non-nil the list of candidates will be filtered externally with a grep command and use ivy-read :dynamic t; so every change in the input will call the external process to update candidates list.

    When counsel-gtags-use-dynamic-list is nil the candidates list from grep -c is passed to emacs without any filter and the filtering is made with ivy-read command, the external process is called only once per invocation, but the list may be too large in some projects. This option is recommended when using tramp and slow connections and/or the expected output of global -c is not extremely large.

    In my use case, nil performs better when using tramp and global -c in the remote host returns ~5000 candidates. When working locally it also performs better in most of the cases.

See also

My other "using global from withing Emacs" package: global-tags.el I stopped using this package (, created) and started using that one, which works best with ivy-xref. This package and global-gtags are really hard to maintain because newcomers have to absorb a lot of hacks so the code can work.

This packages is mostly "make things friendly for ivy", while global-gtags is mostly "fight compilation-mode to present a decent UI". None use Emacs' native xref.el.

emacs-counsel-gtags's People

Contributors

alexmurray avatar dickby avatar ergus avatar fabacino avatar felipelema avatar syohex avatar thanhvg avatar whatacold avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

emacs-counsel-gtags's Issues

Critical issue with counsel-gtags-find-definition and other commands

Hi:

Recently when I try to use some counsel-gtags commands I get this errors: (wrong-number-of-arguments (1 . 2) 0)

Lookign at the stack I get this:

Debugger entered--Lisp error: (wrong-number-of-arguments (1 . 2) 0)
 counsel--elisp-to-pcre()
 counsel-gtags--build-command-to-collect-candidates(#("ClusterManager" 0 14 (face font-lock-type-face fontified t)) ("--result=ctags"))
 counsel-gtags--async-tag-query-process(#("ClusterManager" 0 14 (face font-lock-type-face fontified t)))
 counsel-gtags--async-tag-query(#("ClusterManager" 0 14 (face font-lock-type-face fontified t)))
 ivy--dynamic-collection-cands(#("ClusterManager" 0 14 (face font-lock-type-face fontified t)))
 ivy--reset-state(#s(ivy-state :prompt "Find Definition: " :collection counsel-gtags--async-tag-query :predicate nil :require-match nil :initial-input #("ClusterManager" 0 14 (face font-lock-type-face fontified t)) :history nil :preselect nil :keymap nil :update-fn nil :sort nil :frame #<frame F1 0x5568d334d908> :window #<window 1 on ClusterManager.cpp> :buffer #<buffer ClusterManager.cpp> :text nil :action (1 ("o" identity "default") ("i" ivy--action-insert "insert") ("w" ivy--action-copy "copy")) :unwind #f(compiled-function () #<bytecode 0x1e0c7d770d11>) :re-builder ivy--regex-plus :matcher nil :dynamic-collection t :display-transformer-fn nil :directory "/home/ergo/PhD/nanos6/nanos6_cluster/src/cluster/" :caller counsel-gtags--read-tag :current nil :def nil :ignore t :multi-action nil :extra-props nil))
 ivy-read("Find Definition: " counsel-gtags--async-tag-query :initial-input #("ClusterManager" 0 14 (face font-lock-type-face fontified t)) :unwind #f(compiled-function () #<bytecode 0x1e0c7d770d11>) :dynamic-collection t :caller counsel-gtags--read-tag)
 apply(ivy-read ("Find Definition: " counsel-gtags--async-tag-query :initial-input #("ClusterManager" 0 14 (face font-lock-type-face fontified t)) :unwind #f(compiled-function () #<bytecode 0x1e0c7d770d11>) :dynamic-collection t :caller counsel-gtags--read-tag))
 counsel-gtags--read-tag(definition)
 byte-code("\300\301!C\207" [counsel-gtags--read-tag definition] 2)
 call-interactively(counsel-gtags-find-definition record nil)
 command-execute(counsel-gtags-find-definition record)
 counsel-M-x-action("counsel-gtags-find-definition")
 ivy-call()
 ivy-read("M-x " ("debug-on-entry" "toggle-debug-on-error" "counsel-gtags-find-definition" "package-list-packages" "gpm-mouse-mode" "magit-status" "sudo-edit" "magit-push-to-remote" "man" "undo" "mu4e" "tabify" "copy-file" "magit-pull" "magit-log-all" "cd" "5x5" "amx" "arp" "dbx" "dig" "erc" "ert" "eww" "ftp" "gdb" "irc" "jdb" "lsp" "mpc" "pdb" "pwd" "rsh" "sdb" "xdb" "bang" "calc" "diff" "dirs" "ffap" "gnus" "grep" "help" "ielm" "info" "lice" "life" "mail" "mpuz" "ping" ...) :predicate #f(compiled-function (x) #<bytecode 0xa5d869007dcd8f>) :require-match t :history counsel-M-x-history :action counsel-M-x-action :keymap (keymap (67108908 . counsel--info-lookup-symbol) (67108910 . counsel-find-symbol)) :initial-input nil :caller counsel-M-x)
 counsel-M-x()
 funcall-interactively(counsel-M-x)
 call-interactively(counsel-M-x nil nil)
 command-execute(counsel-M-x)

ivy-call: Symbol’s value as variable is void: line

Hi:
Apart from comment in the previous issue I just found that locally when I try to open a candidate file from the ivy list I get this error message:

 ivy-call: Symbol’s value as variable is void: line

This is local, so nothing to do with tramp.

global-tags performance issue and proposed fix

Hi Felipe:

Today I had an issue with global-tags--get-dbpath that takes too much time when using tramp.

The issue came out trying to use a command like project-switch-to-buffer that calls project--read-project-buffer that basically calls project-current for all the opened buffers calling project--find-in-directory that calls project-find-functions where global-tags-try-project-root is. So the functions in project-find-functions are expected to be as fast as possible.

I thought to report this as an emacs issue but after a while a found that most of the time was taken by global-tags-try-project-root so that makes me think that probably that function needs an important optimization. The time is taken mostly by global-tags--get-dbpath

There are several options:

  1. Lets say a sort of cache to store pairs like: (default-directory . dbpath) everytime global-tags-try-project-root is invoked for the first time for a different default-directory.

  2. Use a buffer-local-variable for the first time we use the function for a buffer. This approach makes to use the slow external process at least once per buffer... so Maybe 1 is a better and simpler approach.

  3. Use a hash-table for same than 1.

Something as simple as (untested)

(defvar global-tags--dbpath-cache (make-hash-table))

(cl-defun global-tags--get-dbpath (&optional (dir default-directory))
  "Filepath for database from DIR."
  (or (gethash dir global-tags--dbpath-cache)
      (when-let* 
        ==bla bla==
	(when (file-exists-p dbpath)
	  (puthash dir dbpath global-tags--dbpath-cache)
          dbpath))))

Another part of the issue is when when-let does not call puthash... because some of the conditions failed. Because the next time the when-let will be called again In that case the solution is to add a dumb value unconditionally like 'empty by default and use some comparisons against it before calling the when-let.

Old link in packages-list

Hi Felipe:
I have seen that in packages-list in elpa they transferred the download repo to you, but the link shown is still the old one from syohex.

So there is some activity (an issue on June 24) and no reply.

Listing (and filtering) tags does not work with Tramp

From #1 (comment)

@Ergus, I was using grep to filter the results, but now that I have a better knowledge of Ivy, I understand this is not the encouraged way to go.

The correct way to approach this is to do "X more chars to go", translating the input as regex and let global do the filtering, but I first wanted to confirm with someone else using this package (you) first.

Are you (and anyone reading this) OK with changing behaviour and force user input for tags?

counsel-gtags-find-definition does not filter symbols

In an empty directory, create the following file a.c:

int the_first_func() {
  return 0;
}

int the_second_func(int x) {
  return 0;
}

int the_third_func(int x) {
  return 0;
}

Then run gtags. global -c now outputs:

the_first_func
the_second_func
the_third_func

Now open a.c in Emacs and call counsel-gtags-find-definition. Type the_ in the minibuffer, and now the minibuffer looks like this, with nothing below this line:

(1/2) Find Definition: the_

However, one would expect all three symbols be filtered. Type the full symbol name followed by "Enter" still correctly take me to the definition.

Issue in global-tags

Hi Felipe:

Sorry for reporting here, but I don't know how to report issues in the other page (I really didn't tried too much either).

The latest changes in global-tags created some issues in my system. Checking the code I see the variable global-tags-exclusive-backend-mode in the global-tags-shared-backend-mode so the shared mode is broken because it never becomes enabled and I get this:

image

get "function definition is void: interactive-call" error when counsel-gtags-dwim is executed

Hello.

My counsel-tags configuration is like this:

(use-package counsel-gtags :ensure t :delight :commands counsel-gtags-mode :bind (:map counsel-gtags-mode-map ("M-." . counsel-gtags-dwim) ("M-," . counsel-gtags-go-backward)) :hook ((swift-mode . counsel-gtags-mode) (swift-mode . ggtags-mode)))

OS: Debian GNU/Linux 10 (buster)
emacs version: 26.1
counsel-tags version: counsel-gtags-20201102.2116

When I execute counsel-gtags-dwin, after pressing 'y' for a new GTAGS file creation, "Symbol’s function definition is void: interactive-call" is reported. I find "interactive-call" in counsel-tags.el at line 464, but have no idea of what it is. I'm sorry for my ignorance about emacs lisp, but could you please point me how to fix it?

Tramp issues

Hi:
The package is not working with tramp. I just tried ggtags and it is working perfectly, so I think you can fix the issue with their code approach to retrieve and call remote processes.

Right now when I try to find a definition I get this in the Message buffer:

Tramp: Opening connection for mn2 using ssh...
Tramp: Sending command ‘exec ssh -q    -e none mn2’
Tramp: Waiting for prompts from remote shell...failed
Tramp: Opening connection for mn2 using ssh...failed
ivy-done: Wrong type argument: char-or-string-p, nil

(mn2 is the server I am connected to.)

Actually it prompts to ask the definition with the right completion but after pressing enter I just get the prompt again, but empty.

counsel-gtags-find-definition gives "(wrong-number-of-arguments (1 . 1) 2)"

Emacs Version: 26.1

This problem seems to lay in counsel-gtags.el#L192

			    (let ((path (executable-find exec t)))

while in Emacs 26.1, the executable-find command only takes on argument. The problem could be fixed on 26.1 if I remove the 't' after 'exec'.

Backtrace

Debugger entered--Lisp error: (wrong-number-of-arguments (1 . 1) 2)
  executable-find("rg" t)
  (let ((path (executable-find exec t))) (if path (progn (throw 'path (concat path " " (cdr (assoc-string exec counsel-gtags--grep-options-alist)))))))
  (closure (t) (exec) (let ((path (executable-find exec t))) (if path (progn (throw 'path (concat path " " (cdr (assoc-string exec counsel-gtags--grep-options-alist))))))))("rg")
  mapc((closure (t) (exec) (let ((path (executable-find exec t))) (if path (progn (throw 'path (concat path " " (cdr (assoc-string exec counsel-gtags--grep-options-alist)))))))) ("rg" "ag" "grep"))
  (catch 'path (mapc (function (lambda (exec) (let ((path (executable-find exec t))) (if path (progn (throw 'path (concat path " " (cdr (assoc-string exec counsel-gtags--grep-options-alist))))))))) counsel-gtags--grep-commands-list) nil)
  (set (make-local-variable 'counsel-gtags--get-grep-command) (catch 'path (mapc (function (lambda (exec) (let ((path (executable-find exec t))) (if path (progn (throw 'path (concat path " " (cdr (assoc-string exec counsel-gtags--grep-options-alist))))))))) counsel-gtags--grep-commands-list) nil))
  (or counsel-gtags--get-grep-command (set (make-local-variable 'counsel-gtags--get-grep-command) (catch 'path (mapc (function (lambda (exec) (let ((path (executable-find exec t))) (if path (progn (throw 'path (concat path " " (cdr (assoc-string exec counsel-gtags--grep-options-alist))))))))) counsel-gtags--grep-com$
  counsel-gtags--get-grep-command-find()
  (concat " | " (counsel-gtags--get-grep-command-find) " " (shell-quote-argument (counsel--elisp-to-pcre (ivy--regex query))))
  (and query (concat " | " (counsel-gtags--get-grep-command-find) " " (shell-quote-argument (counsel--elisp-to-pcre (ivy--regex query)))))
  (concat "global -c " (counsel-gtags--command-options 'definition query nil) (and query (concat " | " (counsel-gtags--get-grep-command-find) " " (shell-quote-argument (counsel--elisp-to-pcre (ivy--regex query))))))
  counsel-gtags--build-command-to-collect-candidates("g_major")
  (let ((command (counsel-gtags--build-command-to-collect-candidates query))) (counsel-gtags--debug-message "Async Command: %s" command) (counsel--async-command command) '("" "Filtering …"))
  (or (ivy-more-chars) (let ((command (counsel-gtags--build-command-to-collect-candidates query))) (counsel-gtags--debug-message "Async Command: %s" command) (counsel--async-command command) '("" "Filtering …")))
  counsel-gtags--async-tag-query("g_major")
  ivy--dynamic-collection-cands("g_major")
  ivy--reset-state(#s(ivy-state :prompt "Find Definition: " :collection counsel-gtags--async-tag-query :predicate nil :require-match nil :initial-input "g_major" :history nil :preselect nil :keymap nil :update-fn nil :sort nil :frame #<frame F1 0xc371b0> :window #<window 1 on xpu_drv.c> :buffer #<buffer xpu_drv.c> :$
  ivy-read("Find Definition: " counsel-gtags--async-tag-query :initial-input "g_major" :unwind (closure (t) nil (counsel-delete-process) (swiper--cleanup)) :dynamic-collection t :caller counsel-gtags--read-tag)
  (list (ivy-read "Find Definition: " (if counsel-gtags-use-dynamic-list (function counsel-gtags--async-tag-query) (counsel-gtags--sync-tag-query)) :initial-input (and counsel-gtags-use-input-at-point (ivy-thing-at-point)) :unwind (function (lambda nil (counsel-delete-process) (swiper--cleanup))) :dynamic-collection$
  call-interactively(counsel-gtags-find-definition nil nil)
  command-execute(counsel-gtags-find-definition)

color codes not getting filtered

Originally posted this on syohex repo before I realized yours is what package actually got installed by use-package ;)

I assume gtags or global are producing output with colors in it, because when I try to find defintions I'm seeing this:

`(1/1) Find Definition: self_only_test

�[30;43mself_only_test�[0m�[K`

Then when I hit enter to pick the definition global complains "invalid regular expression" probably because of those brackets.

I checked my environment and I don't have any GREP_COLORS set (global --help mentions it respects this var).

I checked with C-h v for plausible looking vars for customizing the gtags/global commands but didn't see any.

My global version is a little old, 6.5.6.

@jgarvin

Author
jgarvin commented 23 hours ago
After digging though counsel-gtags.el I saw it was using grep, so I tried:

(setq counsul-grep-command "grep --color=never")

Which did the trick. I also discovered my bashrc sets an alias to enable color for grep -- but that would only be an issue if counsel runs the commands inside a shell, not sure if it does.

@jgarvin

Author
jgarvin commented 15 minutes ago
...Strangely on emacs restart this came back, not sure why. Now these have no effect on the problem:

(setq grep-find-command "grep --color=never")
(setq counsul-grep-command "grep --color=never")

Few parameters for counsel-gtags-path-style

It would be nice to use:

(setq counsel-gtags-path-style 'abslib)
or
(setq counsel-gtags-path-style 'shorter)

With short (root) filenames, navigation does not work for GTAGSLIBPATH.

global:invalid regular expression.

Hi, about ten days ago, my gtags can't be used normally, when I use counsel-gtags-find-definition and counsel-gtags-find-reference commands, emacs will give me an error message: global:invalid regular expression.

some version information :

OS: Ubuntu 1604
Emacs version: 26.2
Global version: 6.6
My emacs config:

(use-package counsel-gtags :ensure t
:init
(add-hook 'c-mode-hook 'counsel-gtags-mode)
(add-hook 'after-save-hook 'counsel-gtags-update-tags)
:bind (:map counsel-gtags-mode-map
("M-t" . counsel-gtags-find-definition)
("M-r" . counsel-gtags-find-reference)
("M-s" . counsel-gtags-find-symbol)
("M-," . counsel-gtags-go-backward)))


I've tried to reinstall global and counsel-gtags to address the problem,but I failed. I've noticed that counsel-gtags have been updated recently,so I'm guessing if it's because of the gtags update. When I rolled back the gtags version to 5df12da 29 days ago, the problem went away, but I don't know why?

find_tag_other_window?

Hi, do you think it makes sense to add find-other-window like behavior when called with universal prefix for example??

It shouldn't be so complex right? And with a change in counsel-gtags--jump-to it could benefit all the commands.

counsel-gtags-find-symbol shows error code 1

Running in a sandboxed Emacs using only

(eval-when-compile
  (add-to-list 'load-path "~/use-package")
  (require 'use-package))

(use-package counsel
  :ensure t)
(use-package counsel-gtags
  :ensure t)

and generating the database with global --gtagslabel=pygments . (and ctags, new-ctags) as well, I end up with error code 1 when running counsel-gtags-find-symbol after typing three chars.

Is there any way to look into what error code 1 means?

System Information:

  • Emacs 27.1
  • GNU Global 6.6.5
  • Universal Ctags 5.9.0
  • Exuberant Ctags 5.8

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.