Skip to content

Commit

Permalink
fix issue #191
Browse files Browse the repository at this point in the history
add support for GNU Global
  • Loading branch information
Yggdroot committed Apr 18, 2019
1 parent 9a1e62c commit b9cc519
Show file tree
Hide file tree
Showing 25 changed files with 1,197 additions and 56 deletions.
42 changes: 19 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
LeaderF
=======

This plugin is mainly used for locating files, buffers, mrus, tags in large project.
This plugin is mainly used for locating files, buffers, mrus, ctags, gtags, etc. in large project.

- Written in Python.
- Support fuzzy and regex searching.
Expand Down Expand Up @@ -130,20 +130,16 @@ If [!] is given, enter normal mode directly.
use `:Leaderf <subcommand> -h` to get specific help of subcommand, e.g., `:Leaderf rg -h`

```
usage: Leaderf[!] rg [-h] [-A <NUM>] [-B <NUM>] [-C <NUM>]
[--context-separator <SEPARATOR>] [-e <PATTERN>...] [-F]
[-i] [-L] [-P] [-S] [-s] [-v] [-w] [-x] [--hidden]
[--no-config] [--no-ignore] [--no-ignore-global]
[--no-ignore-parent] [--no-ignore-vcs]
[--no-pcre2-unicode] [-E <ENCODING>] [-M <NUM>]
[-m <NUM>] [--max-depth <NUM>] [--max-filesize <NUM+SUFFIX?>]
[--path-separator <SEPARATOR>] [--sort <SORTBY>]
[--sortr <SORTBY>] [-f <PATTERNFILE>...] [-g <GLOB>...]
[--iglob <GLOB>...] [--ignore-file <PATH>...]
[--type-add <TYPE_SPEC>...] [-t <TYPE>...] [-T <TYPE>...]
[--current-buffer | --all-buffers] [--recall] [--append]
[--match-path] [--wd-mode <MODE>] [--reverse]
[--stayOpen] [--input <INPUT> | --cword]
usage: Leaderf[!] rg [-h] [-A <NUM>] [-B <NUM>] [-C <NUM>] [--context-separator <SEPARATOR>]
[-e <PATTERN>...] [-F] [-i] [-L] [-P] [-S] [-s] [-v] [-w] [-x] [--hidden]
[--no-config] [--no-ignore] [--no-ignore-global] [--no-ignore-parent]
[--no-ignore-vcs] [--no-pcre2-unicode] [-E <ENCODING>] [-M <NUM>] [-m <NUM>]
[--max-depth <NUM>] [--max-filesize <NUM+SUFFIX?>] [--path-separator <SEPARATOR>]
[--sort <SORTBY>] [--sortr <SORTBY>] [-f <PATTERNFILE>...] [-g <GLOB>...]
[--iglob <GLOB>...] [--ignore-file <PATH>...] [--type-add <TYPE_SPEC>...]
[-t <TYPE>...] [-T <TYPE>...] [--current-buffer | --all-buffers] [--recall]
[--append] [--match-path] [--wd-mode <MODE>] [--reverse] [--stayOpen]
[--input <INPUT> | --cword]
[--top | --bottom | --left | --right | --belowright | --aboveleft | --fullScreen]
[--nameOnly | --fullPath | --fuzzy | --regexMode] [--nowrap]
[<PATH> [<PATH> ...]]
Expand Down Expand Up @@ -175,8 +171,8 @@ specific arguments:
-w, --word-regexp Only show matches surrounded by word boundaries. This is roughly equivalent to
putting \b before and after all of the search patterns.
-x, --line-regexp Only show matches surrounded by line boundaries.
--hidden Search hidden files and directories. By default, hidden files and directories
are skipped.
--hidden Search hidden files and directories. By default, hidden files and directories are
skipped.
--no-config Never read configuration files. When this flag is present, rg will not respect
the RIPGREP_CONFIG_PATH environment variable.
--no-ignore Don't respect ignore files (.gitignore, .ignore, etc.). This implies
Expand All @@ -186,8 +182,8 @@ specific arguments:
`$HOME/.config/git/ignore`).
--no-ignore-parent Don't respect ignore files (.gitignore, .ignore, etc.) in parent directories.
--no-ignore-vcs Don't respect version control ignore files (.gitignore, etc.).
--no-pcre2-unicode When PCRE2 matching is enabled, this flag will disable
Unicode mode, which is otherwise enabled by default.
--no-pcre2-unicode When PCRE2 matching is enabled, this flag will disable Unicode mode, which is
otherwise enabled by default.
-E <ENCODING>, --encoding <ENCODING>
Specify the text encoding that rg will use on all files searched.
-M <NUM>, --max-columns <NUM>
Expand All @@ -202,8 +198,8 @@ specific arguments:
--sort <SORTBY> This flag enables sorting of results in ascending order.
--sortr <SORTBY> This flag enables sorting of results in descending order.
-f <PATTERNFILE>..., --file <PATTERNFILE>...
Search for patterns from the given file, with one pattern per line.
(This option can be provided multiple times.)
Search for patterns from the given file, with one pattern per line.(This option
can be provided multiple times.)
-g <GLOB>..., --glob <GLOB>...
Include or exclude files and directories for searching that match the given
glob.(This option can be provided multiple times.)
Expand All @@ -224,8 +220,8 @@ specific arguments:
--recall Recall last search. If the result window is closed, reopen it.
--append Append to the previous search results.
--match-path Match the file path when fuzzy searching.
--wd-mode <MODE> Specify the working directory mode, value has the same
meaning as g:Lf_WorkingDirectoryMode.
--wd-mode <MODE> Specify the working directory mode, value has the same meaning as
g:Lf_WorkingDirectoryMode.
common arguments:
--reverse show results in bottom-up order
Expand Down
17 changes: 16 additions & 1 deletion autoload/leaderf.vim
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,12 @@ call s:InitDict('g:Lf_PreviewResult', {
call s:InitDict('g:Lf_NormalMap', {})
call s:InitVar('g:Lf_Extensions', {})
call s:InitDict('g:Lf_CtagsFuncOpts', {})
call s:InitDict('g:Lf_MaxCount', 2000000)
call s:InitVar('g:Lf_MaxCount', 2000000)
call s:InitDict('g:Lf_GtagsfilesCmd', {
\ '.git': 'git ls-files --recurse-submodules',
\ '.hg': 'hg files',
\ 'default': 'rg --no-messages --files'
\})

let s:Lf_CommandMap = {
\ '<C-A>': ['<C-A>'],
Expand Down Expand Up @@ -239,3 +244,13 @@ function! leaderf#LfPy(cmd)
exec g:Lf_py . a:cmd
endfunction

" return the visually selected text and quote it with double quote
function! leaderf#visual()
try
let x_save = @x
norm! gv"xy
return '"' . escape(@x, '"') . '"'
finally
let @x = x_save
endtry
endfunction
28 changes: 28 additions & 0 deletions autoload/leaderf/Any.vim
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ let g:Lf_Helps = {
\ "colorscheme": "switch between colorschemes",
\ "self": "execute the commands of itself",
\ "rg": "grep using rg",
\ "gtags": "navigate tags using the gtags",
\ }

let g:Lf_Arguments = {
Expand Down Expand Up @@ -138,6 +139,33 @@ let g:Lf_Arguments = {
\ {"name": ["--match-path"], "nargs": 0, "help": "Match the file path when fuzzy searching."},
\ {"name": ["--wd-mode"], "nargs": 1, "metavar": "<MODE>", "help": "Specify the working directory mode, value has the same meaning as g:Lf_WorkingDirectoryMode."},
\ ],
\ "gtags":[
\ [
\ {"name": ["--update"], "nargs": 0, "help": "Create tag files if tag files do not exist, update the tag files otherwise."},
\ {"name": ["--remove"], "nargs": 0, "help": "Remove the tag files generated."},
\ ],
\ {"name": ["--accept-dotfiles"], "nargs": 0, "help": "Accept files and directories whose names begin with a dot. By default, gtags ignores them."},
\ {"name": ["--skip-unreadable"], "nargs": 0, "help": "Skip unreadable files."},
\ {"name": ["--gtagsconf"], "nargs": 1, "metavar": "<FILE>", "help": "Set environment variable GTAGSCONF to <FILE>."},
\ {"name": ["--gtagslabel"], "nargs": 1, "metavar": "<LABEL>", "help": "Set environment variable GTAGSLABEL to <LABEL>."},
\ {"name": ["--skip-symlink"], "nargs": "?", "metavar": "<TYPE>", "help": "Skip symbolic links. If type is 'f' then skip only symbolic links for file, else if 'd' then skip only symbolic links for directory. The default value of type is 'a' (all symbolic links)."},
\ {"name": ["--gtagslibpath"], "nargs": "+", "metavar": "<PATH>", "help": "Specify the paths to search for library functions."},
\ [
\ {"name": ["-d", "--definition"], "nargs": 1, "metavar": "<PATTERN>", "help": "Show locations of definitions."},
\ {"name": ["-r", "--reference"], "nargs": 1, "metavar": "<PATTERN>", "help": "Show reference to a symbol which has definitions."},
\ {"name": ["-s", "--symbol"], "nargs": 1, "metavar": "<PATTERN>", "help": "Show reference to a symbol which has no definition."},
\ {"name": ["-g", "--grep"], "nargs": 1, "metavar": "<PATTERN>", "help": "Show all lines which match to the <PATTERN>."},
\ {"name": ["--by-context"], "nargs": 0, "help": "Decide tag type by context at cursor position. If the context is a definition of the pattern then use -r, else if there is at least one definition of the pattern then use -d, else use -s. Regular expression is not allowed for pattern."},
\ ],
\ {"name": ["-i", "--ignore-case"], "nargs": 0, "help": "Ignore case distinctions in the pattern."},
\ {"name": ["--literal"], "nargs": 0, "help": "Execute literal search instead of regular expression search."},
\ {"name": ["--path-style"], "nargs": 1, "metavar": "<FORMAT>", "help": "Show path names using <FORMAT>, which may be one of: `relative`, `absolute`, `shorter`, `abslib` or `through`. `relative` means relative path. `absolute` means absolute path. `shorter` means the shorter one of relative and absolute path. `abslib` means absolute path for libraries (GTAGSLIBPATH) and relative path for the rest. `through` means the relative path from the project root directory (internal format of GPATH). The default is `relative`."},
\ {"name": ["-S", "--scope"], "nargs": 1, "metavar": "<DIR>", "help": "Show only tags which exist under <DIR> directory."},
\ {"name": ["--recall"], "nargs": 0, "help": "Recall last search. If the result window is closed, reopen it."},
\ {"name": ["--append"], "nargs": 0, "help": "Append to the previous search results."},
\ {"name": ["--match-path"], "nargs": 0, "help": "Match the file path when fuzzy searching."},
\ {"name": ["--all"], "nargs": 0, "help": "search tags in all opening buffers"},
\ ],
\}

let g:Lf_CommonArguments = [
Expand Down
55 changes: 55 additions & 0 deletions autoload/leaderf/Gtags.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
" ============================================================================
" File: Gtags.vim
" Description:
" Author: Yggdroot <[email protected]>
" Website: https://github.com/Yggdroot
" Note:
" License: Apache License, Version 2.0
" ============================================================================

if leaderf#versionCheck() == 0 " this check is necessary
finish
endif

exec g:Lf_py "from leaderf.gtagsExpl import *"
exec g:Lf_py "from leaderf.utils import *"

function! leaderf#Gtags#Maps()
nmapclear <buffer>
nnoremap <buffer> <silent> <CR> :exec g:Lf_py "gtagsExplManager.accept()"<CR>
nnoremap <buffer> <silent> o :exec g:Lf_py "gtagsExplManager.accept()"<CR>
nnoremap <buffer> <silent> <2-LeftMouse> :exec g:Lf_py "gtagsExplManager.accept()"<CR>
nnoremap <buffer> <silent> x :exec g:Lf_py "gtagsExplManager.accept('h')"<CR>
nnoremap <buffer> <silent> v :exec g:Lf_py "gtagsExplManager.accept('v')"<CR>
nnoremap <buffer> <silent> t :exec g:Lf_py "gtagsExplManager.accept('t')"<CR>
nnoremap <buffer> <silent> p :exec g:Lf_py "gtagsExplManager._previewResult(True)"<CR>
nnoremap <buffer> <silent> q :exec g:Lf_py "gtagsExplManager.quit()"<CR>
" nnoremap <buffer> <silent> <Esc> :exec g:Lf_py "gtagsExplManager.quit()"<CR>
nnoremap <buffer> <silent> i :exec g:Lf_py "gtagsExplManager.input()"<CR>
nnoremap <buffer> <silent> <Tab> :exec g:Lf_py "gtagsExplManager.input()"<CR>
nnoremap <buffer> <silent> <F1> :exec g:Lf_py "gtagsExplManager.toggleHelp()"<CR>
nnoremap <buffer> <silent> d :exec g:Lf_py "gtagsExplManager.deleteCurrentLine()"<CR>
if has_key(g:Lf_NormalMap, "Gtags")
for i in g:Lf_NormalMap["Gtags"]
exec 'nnoremap <buffer> <silent> '.i[0].' '.i[1]
endfor
endif
endfunction

function! leaderf#Gtags#startExpl(win_pos, ...)
exec g:Lf_py "<< EOF"
gtagsExplManager.startExplorer(vim.eval("a:win_pos"))
EOF
endfunction

function! leaderf#Gtags#updateGtags(filename, single_update)
exec g:Lf_py "<< EOF"
gtagsExplManager.updateGtags(lfDecode(vim.eval("a:filename")), True if int(vim.eval("a:single_update")) else False)
EOF
endfunction

function! leaderf#Gtags#TimerCallback(id)
exec g:Lf_py "<< EOF"
gtagsExplManager._workInIdle(bang=True)
EOF
endfunction
1 change: 1 addition & 0 deletions autoload/leaderf/Rg.vim
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ function! leaderf#Rg#Maps()
nnoremap <buffer> <silent> i :exec g:Lf_py "rgExplManager.input()"<CR>
nnoremap <buffer> <silent> <Tab> :exec g:Lf_py "rgExplManager.input()"<CR>
nnoremap <buffer> <silent> <F1> :exec g:Lf_py "rgExplManager.toggleHelp()"<CR>
nnoremap <buffer> <silent> d :exec g:Lf_py "rgExplManager.deleteCurrentLine()"<CR>
if has_key(g:Lf_NormalMap, "Rg")
for i in g:Lf_NormalMap["Rg"]
exec 'nnoremap <buffer> <silent> '.i[0].' '.i[1]
Expand Down
2 changes: 1 addition & 1 deletion autoload/leaderf/fuzzyMatch_C/fuzzyEngine.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ struct FuzzyEngine
pthread_mutex_lock(&(queue).mutex); \
--(queue).unfinished_tasks; \
if ( (queue).unfinished_tasks <= 0 ) \
pthread_cond_broadcast(&(queue).task_cond); \
pthread_cond_signal(&(queue).task_cond); \
pthread_mutex_unlock(&(queue).mutex); \
} while(0)

Expand Down
48 changes: 43 additions & 5 deletions autoload/leaderf/python/leaderf/anyExpl.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ def _createHelp(self):
help.append('" v : open file under cursor in a vertically split window')
help.append('" t : open file under cursor in a new tabpage')
help.append('" i/<Tab> : switch to input mode')
help.append('" q/<Esc> : quit')
help.append('" q : quit')
help.append('" <F1> : toggle this help')
help.append('" ---------------------------------------------------------')
return help
Expand Down Expand Up @@ -500,6 +500,35 @@ def split(self):
self.whitespace_split = True
return list(self)

class LfHelpFormatter(argparse.HelpFormatter):
def __init__(self,
prog,
indent_increment=2,
max_help_position=24,
width=105):
super(LfHelpFormatter, self).__init__(prog, indent_increment, max_help_position, width)

gtags_usage = """
\n
Leaderf[!] gtags [-h] [--remove] [--recall] [--all]
Leaderf[!] gtags --update [--gtagsconf <FILE>] [--gtagslabel <LABEL>] [--accept-dotfiles]
[--skip-unreadable] [--skip-symlink [<TYPE>]] [--gtagslibpath <PATH> [<PATH> ...]]
Leaderf[!] gtags -d <PATTERN> [-i] [--literal] [--path-style <FORMAT>] [-S <DIR>] [--append]
[--match-path] [--gtagsconf <FILE>] [--gtagslabel <LABEL>] [COMMON_OPTIONS]
Leaderf[!] gtags -r <PATTERN> [-i] [--literal] [--path-style <FORMAT>] [-S <DIR>] [--append]
[--match-path] [--gtagsconf <FILE>] [--gtagslabel <LABEL>] [COMMON_OPTIONS]
Leaderf[!] gtags -s <PATTERN> [-i] [--literal] [--path-style <FORMAT>] [-S <DIR>] [--append]
[--match-path] [--gtagsconf <FILE>] [--gtagslabel <LABEL>] [COMMON_OPTIONS]
Leaderf[!] gtags -g <PATTERN> [-i] [--literal] [--path-style <FORMAT>] [-S <DIR>] [--append]
[--match-path] [--gtagsconf <FILE>] [--gtagslabel <LABEL>] [COMMON_OPTIONS]
Leaderf[!] gtags --by-context [-i] [--literal] [--path-style <FORMAT>] [-S <DIR>] [--append]
[--match-path] [--gtagsconf <FILE>] [--gtagslabel <LABEL>] [COMMON_OPTIONS]
[COMMON_OPTIONS]: [--reverse] [--stayOpen] [--input <INPUT> | --cword]
[--top | --bottom | --left | --right | --belowright | --aboveleft | --fullScreen]
[--nameOnly | --fullPath | --fuzzy | --regexMode] [--nowrap]
\n
"""

class AnyHub(object):
def __init__(self):
Expand Down Expand Up @@ -617,6 +646,9 @@ def _default_action(self, category, positional_args, arguments, *args, **kwargs)
elif category == "rg":
from .rgExpl import rgExplManager
manager = rgExplManager
elif category == "gtags":
from .gtagsExpl import gtagsExplManager
manager = gtagsExplManager
else:
lfCmd("call %s('%s')" % (lfEval("g:Lf_PythonExtensions['%s'].registerFunc" % category), category))
manager = self._pyext_manages[category]
Expand All @@ -639,7 +671,7 @@ def _default_action(self, category, positional_args, arguments, *args, **kwargs)

def start(self, arg_line, *args, **kwargs):
if self._parser is None:
self._parser = argparse.ArgumentParser(prog="Leaderf[!]", epilog="If [!] is given, enter normal mode directly.")
self._parser = argparse.ArgumentParser(prog="Leaderf[!]", formatter_class=LfHelpFormatter, epilog="If [!] is given, enter normal mode directly.")
self._add_argument(self._parser, lfEval("g:Lf_CommonArguments"), [])
subparsers = self._parser.add_subparsers(title="subcommands", description="", help="")
extensions = itertools.chain(lfEval("keys(g:Lf_Extensions)"), lfEval("keys(g:Lf_PythonExtensions)"))
Expand All @@ -656,7 +688,10 @@ def start(self, arg_line, *args, **kwargs):
help = lfEval("g:Lf_Helps['%s']" % category)
arg_def = lfEval("g:Lf_Arguments['%s']" % category)

parser = subparsers.add_parser(category, help=help, epilog="If [!] is given, enter normal mode directly.")
if category == 'gtags':
parser = subparsers.add_parser(category, usage=gtags_usage, formatter_class=LfHelpFormatter, help=help, epilog="If [!] is given, enter normal mode directly.")
else:
parser = subparsers.add_parser(category, help=help, formatter_class=LfHelpFormatter, epilog="If [!] is given, enter normal mode directly.")
group = parser.add_argument_group('specific arguments')
self._add_argument(group, arg_def, positional_args)

Expand All @@ -666,8 +701,11 @@ def start(self, arg_line, *args, **kwargs):
parser.set_defaults(start=partial(self._default_action, category, positional_args))

try:
# do not produce an error when extra arguments are present
the_args = self._parser.parse_known_args(LfShlex(arg_line, posix=False).split())[0]
# # do not produce an error when extra arguments are present
# the_args = self._parser.parse_known_args(LfShlex(arg_line, posix=False).split())[0]

# produce an error when extra arguments are present
the_args = self._parser.parse_args(LfShlex(arg_line, posix=False).split())
arguments = vars(the_args)
arguments = arguments.copy()
del arguments["start"]
Expand Down
Loading

0 comments on commit b9cc519

Please sign in to comment.