From 7b3e6c25b64be3f596465a2dd3d5dba7844e7a74 Mon Sep 17 00:00:00 2001 From: Shengyu Zhang Date: Thu, 1 Apr 2021 01:39:03 +0800 Subject: [PATCH 01/11] Remove duplicated newline --- sphinxnotes/snippet/table.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sphinxnotes/snippet/table.py b/sphinxnotes/snippet/table.py index 7edcb4c..e51e25b 100644 --- a/sphinxnotes/snippet/table.py +++ b/sphinxnotes/snippet/table.py @@ -33,7 +33,7 @@ def tablify(indexes: Dict[IndexID,Index], kinds:str, width:int) -> Iterator[str] ellipsis.ellipsis(COLUMNS[1].upper(), kind_width, blank_sym=' '), ellipsis.ellipsis(COLUMNS[2].upper(), excerpt_width, blank_sym=' '), ellipsis.ellipsis(COLUMNS[3].upper(), path_width, blank_sym=' ' ), - COLUMNS[4].upper()]) + '\n' + COLUMNS[4].upper()]) yield header # Write rows @@ -46,5 +46,5 @@ def tablify(indexes: Dict[IndexID,Index], kinds:str, width:int) -> Iterator[str] ellipsis.ellipsis(f'[{index[0]}]', kind_width, blank_sym=' '), # Kind ellipsis.ellipsis(index[1], excerpt_width, blank_sym=' '), # Excerpt ellipsis.join(index[2], path_width, path_comp_width, blank_sym=' ' ), # Titleppath - ','.join(index[3])]) + '\n' # Keywords + ','.join(index[3])]) # Keywords yield row From 546b98302c9661ac3737d626a02893ef4f41537d Mon Sep 17 00:00:00 2001 From: Shengyu Zhang Date: Thu, 1 Apr 2021 01:39:33 +0800 Subject: [PATCH 02/11] Add zsh plugin --- MANIFEST.in | 1 + integration/plugin.zsh | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 integration/plugin.zsh diff --git a/MANIFEST.in b/MANIFEST.in index 8c37b94..59765f6 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2,3 +2,4 @@ include README.rst include LICENSE recursive-include doc * prune doc/_build +include utils/plugin.zsh diff --git a/integration/plugin.zsh b/integration/plugin.zsh new file mode 100644 index 0000000..05984f8 --- /dev/null +++ b/integration/plugin.zsh @@ -0,0 +1,34 @@ +# Z Shell integration for sphinxnotes-snippet +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# :Author: Shengyu Zhang +# :Date: 2021-03-20 +# :License: BSD + +snippet="snippet" + +# $1: kinds +function snippet_list() { + $snippet list --kinds $1 | \ + fzf --with-nth 2.. --no-hscroll --header-lines 1 | \ + cut -d ' ' -f1 +} + +function snippet_view() { + $snippet get --text $(snippet_list c) +} + +function snippet_edit() { + $EDITOR $($snippet get --file $(snippet_list c)) +} + +# Define a widget, mapped to our function above. +zle -N snippet_view +zle -N snippet_edit + +# Bind it to ctrl-kv +bindkey "^kv" snippet_view +# Bind it to ctrl-ke +bindkey "^ke" snippet_edit + +# vim: set shiftwidth=2: From 7b8402263099cecdebb9c0f786afcd271dc47887 Mon Sep 17 00:00:00 2001 From: Shengyu Zhang Date: Thu, 1 Apr 2021 01:40:43 +0800 Subject: [PATCH 03/11] Integration subcommand --- sphinxnotes/snippet/cli.py | 49 ++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/sphinxnotes/snippet/cli.py b/sphinxnotes/snippet/cli.py index 4474b8e..f707eab 100644 --- a/sphinxnotes/snippet/cli.py +++ b/sphinxnotes/snippet/cli.py @@ -12,6 +12,7 @@ from typing import List from os import path from textwrap import dedent +from shutil import get_terminal_size from xdg.BaseDirectory import xdg_config_home @@ -43,44 +44,39 @@ def main(argv:List[str]=sys.argv[1:]) -> int: # Init subcommands subparsers = parser.add_subparsers() - mgmtparser = subparsers.add_parser('stat', - aliases=['s'], + mgmtparser = subparsers.add_parser('stat', aliases=['s'], formatter_class=HelpFormatter, help='snippets statistic') mgmtparser.set_defaults(func=_on_command_mgmt) - listparser = subparsers.add_parser('list', - aliases=['l'], + listparser = subparsers.add_parser('list', aliases=['l'], formatter_class=HelpFormatter, help='list snippet indexes, columns of indexes: %s' % VISIABLE_COLUMNS) - listparser.add_argument('--kinds', '-k', - action='store_true', - default='*', + listparser.add_argument('--kinds', '-k', type=str, nargs=1, default='*', help='list specified kinds only') - listparser.add_argument('--width', '-w', - action='store_true', - default=120, + listparser.add_argument('--width', '-w', nargs=1, type=int, + default=get_terminal_size((120, 0)).columns, help='width in characters of output') listparser.set_defaults(func=_on_command_list) - getparser = subparsers.add_parser('get', - aliases=['g'], + getparser = subparsers.add_parser('get', aliases=['g'], formatter_class=HelpFormatter, help='get information of snippet by index ID') - getparser.add_argument('--file', '-f', - action='store_true', + getparser.add_argument('--file', '-f', action='store_true', help='get source file path of snippet') - getparser.add_argument('--text', '-t', - action='store_true', - default=True, + getparser.add_argument('--text', '-t', action='store_true', default=True, help='get source reStructuredText of snippet') - getparser.add_argument('index_id', - type=str, - nargs='+', - help='index ID') + getparser.add_argument('index_id', type=str, nargs='+', help='index ID') getparser.set_defaults(func=_on_command_get) + igparser = subparsers.add_parser('integration', aliases=['i'], + formatter_class=HelpFormatter, + help='integration related commands') + igparser.add_argument('--zsh', '-z', action='store_true', help='dump zsh plugin') + igparser.set_defaults(func=_on_command_integration, parser=igparser) + + # Parse command line arguments args = parser.parse_args(argv) @@ -100,6 +96,8 @@ def main(argv:List[str]=sys.argv[1:]) -> int: # Call subcommand if hasattr(args, 'func'): args.func(args) + else: + parser.print_help() def _on_command_mgmt(args:argparse.Namespace): @@ -133,5 +131,14 @@ def _on_command_get(args:argparse.Namespace): print('\n'.join(item.snippet.text())) +def _on_command_integration(args:argparse.Namespace): + # NOTE: files are included by MANIFEST.in + if args.zsh: + with open('integration/plugin.zsh', 'r') as f: + print(f.read()) + return + args.parser.print_help() + + if __name__ == '__main__': sys.exit(main()) From e2ecd79d8530604924e74e28f33ca7313e7e198c Mon Sep 17 00:00:00 2001 From: Shengyu Zhang Date: Thu, 1 Apr 2021 12:24:45 +0800 Subject: [PATCH 04/11] Fix get --file --- sphinxnotes/snippet/cli.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sphinxnotes/snippet/cli.py b/sphinxnotes/snippet/cli.py index f707eab..8ff069e 100644 --- a/sphinxnotes/snippet/cli.py +++ b/sphinxnotes/snippet/cli.py @@ -125,9 +125,10 @@ def _on_command_get(args:argparse.Namespace): if not item: print('no such index ID', file=sys.stderr) sys.exit(1) + # FIXME: get multi attrs at once if args.file: print(item.snippet.file()) - if args.text: + elif args.text: print('\n'.join(item.snippet.text())) From 2aefdacacacd70b4364b4b9b6962457d0380f22d Mon Sep 17 00:00:00 2001 From: Shengyu Zhang Date: Thu, 1 Apr 2021 12:31:34 +0800 Subject: [PATCH 05/11] Optional argument do not need nargs --- sphinxnotes/snippet/cli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sphinxnotes/snippet/cli.py b/sphinxnotes/snippet/cli.py index 8ff069e..5f76448 100644 --- a/sphinxnotes/snippet/cli.py +++ b/sphinxnotes/snippet/cli.py @@ -53,9 +53,9 @@ def main(argv:List[str]=sys.argv[1:]) -> int: formatter_class=HelpFormatter, help='list snippet indexes, columns of indexes: %s' % VISIABLE_COLUMNS) - listparser.add_argument('--kinds', '-k', type=str, nargs=1, default='*', + listparser.add_argument('--kinds', '-k', type=str, default='*', help='list specified kinds only') - listparser.add_argument('--width', '-w', nargs=1, type=int, + listparser.add_argument('--width', '-w', type=int, default=get_terminal_size((120, 0)).columns, help='width in characters of output') listparser.set_defaults(func=_on_command_list) From fa8674bf3b110adf24ad2ec51c50ebc224af79f5 Mon Sep 17 00:00:00 2001 From: Shengyu Zhang Date: Thu, 1 Apr 2021 12:45:38 +0800 Subject: [PATCH 06/11] Dont binding by default --- integration/plugin.zsh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/integration/plugin.zsh b/integration/plugin.zsh index 05984f8..08f82e8 100644 --- a/integration/plugin.zsh +++ b/integration/plugin.zsh @@ -4,6 +4,11 @@ # :Author: Shengyu Zhang # :Date: 2021-03-20 # :License: BSD +# +# The recommanded key bindings are:: +# +# bindkey ^kv snippet-view +# bindkey ^ke snippet-edit snippet="snippet" @@ -19,16 +24,11 @@ function snippet_view() { } function snippet_edit() { - $EDITOR $($snippet get --file $(snippet_list c)) + $EDITOR $($snippet get --file $(snippet_list dc)) } # Define a widget, mapped to our function above. -zle -N snippet_view -zle -N snippet_edit - -# Bind it to ctrl-kv -bindkey "^kv" snippet_view -# Bind it to ctrl-ke -bindkey "^ke" snippet_edit +zle -N snippet-view snippet_view +zle -N snippet-edit snippet_edit # vim: set shiftwidth=2: From 558061ed46ab63a31f72f8d05c94ad49d4ca90ca Mon Sep 17 00:00:00 2001 From: Shengyu Zhang Date: Thu, 1 Apr 2021 03:01:22 +0800 Subject: [PATCH 07/11] Add neovim integration script --- integration/plugin.nvim | 89 ++++++++++++++++++++++++++++++++++++++ sphinxnotes/snippet/cli.py | 7 ++- 2 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 integration/plugin.nvim diff --git a/integration/plugin.nvim b/integration/plugin.nvim new file mode 100644 index 0000000..8f8bffe --- /dev/null +++ b/integration/plugin.nvim @@ -0,0 +1,89 @@ +" NeoVim integration for sphinxnotes-snippet +" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +" +" :Author: Shengyu Zhang +" :Date: 2021-04-01 +" :License: BSD +" +" NOTE: junegunn/fzf.vim is required +" +" The recommanded key bindings are:: +" +" nmap v :call g:SphinxNotesSnippetListAndView() +" nmap e :call g:SphinxNotesSnippetListAndEdit() + + +let s:snippet = 'snippet' + +function! s:SplitID(row) + return split(a:row, ' ')[0] +endfunction + +function! g:SphinxNotesSnippetList(callback, kinds) + let cmd = [s:snippet, 'list', + \ '--kinds', a:kinds, + \ '--width', &columns - 2, + \ ] + call fzf#run({ + \ 'source': join(cmd, ' '), + \ 'sink': a:callback, + \ 'options': ['--with-nth', '2..', '--no-hscroll', '--header-lines', '1'], + \ }) +endfunction + +function! g:SphinxNotesSnippetListAndView() + function! s:CallView(selection) + call g:SphinxNotesSnippetView(s:SplitID(a:selection)) + endfunction + call g:SphinxNotesSnippetList(function('s:CallView'), 'c') +endfunction + +" https://github.com/anhmv/vim-float-window/blob/master/plugin/float-window.vim +function! g:SphinxNotesSnippetView(id) + let height = float2nr((&lines - 2) / 1.5) + let row = float2nr((&lines - height) / 2) + let width = float2nr(&columns / 1.5) + let col = float2nr((&columns - width) / 2) + + " Main Window + let opts = { + \ 'relative': 'editor', + \ 'style': 'minimal', + \ 'width': width, + \ 'height': height, + \ 'col': col, + \ 'row': row, + \ } + + let buf = nvim_create_buf(v:false, v:true) + " Global for :call + let g:sphinx_notes_snippet_win = nvim_open_win(buf, v:true, opts) + + " The content is always reStructuredText for now + set filetype=rst + " Press enter to return + nmap :call nvim_win_close(g:sphinx_notes_snippet_win, v:true) + + let cmd = [s:snippet, 'get', '--text', a:id] + execute '$read !' . join(cmd, ' ') + execute '$read !' . '..' + call append(line('$'), [ + \ '.. Inserted By sphinxnotes-snippet:', + \ '', + \ ' Press to return']) +endfunction + +function! g:SphinxNotesSnippetEdit(id) + let cmd = [s:snippet, 'get', '--file', a:id] + execute '$tabedit ' . system(join(cmd, ' ')) +endfunction + +function! g:SphinxNotesSnippetListAndEdit() + function! s:CallEdit(selection) + call g:SphinxNotesSnippetEdit(s:SplitID(a:selection)) + endfunction + call g:SphinxNotesSnippetList(function('s:CallEdit'), 'dc') +endfunction + +" vim: set shiftwidth=2: +" vim: set filetype=vim: diff --git a/sphinxnotes/snippet/cli.py b/sphinxnotes/snippet/cli.py index 5f76448..6b721dc 100644 --- a/sphinxnotes/snippet/cli.py +++ b/sphinxnotes/snippet/cli.py @@ -73,7 +73,8 @@ def main(argv:List[str]=sys.argv[1:]) -> int: igparser = subparsers.add_parser('integration', aliases=['i'], formatter_class=HelpFormatter, help='integration related commands') - igparser.add_argument('--zsh', '-z', action='store_true', help='dump zsh plugin') + igparser.add_argument('--zsh', '-z', action='store_true', help='dump zsh integration script') + igparser.add_argument('--nvim', '-n', action='store_true', help='dump neovim integration script') igparser.set_defaults(func=_on_command_integration, parser=igparser) @@ -138,6 +139,10 @@ def _on_command_integration(args:argparse.Namespace): with open('integration/plugin.zsh', 'r') as f: print(f.read()) return + if args.nvim: + with open('integration/plugin.nvim', 'r') as f: + print(f.read()) + return args.parser.print_help() From 0a35f70e97f643cb9e08bf26378fbf3fd3e91788 Mon Sep 17 00:00:00 2001 From: Shengyu Zhang Date: Thu, 1 Apr 2021 16:09:53 +0800 Subject: [PATCH 08/11] Better make install --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 82ed607..f6fd3ca 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ upload: dist/ .PHONY: install install: - $(PY) -m pip install -U dist/*.whl + $(PY) -m pip install --user --no-deps --force-reinstall dist/*.whl .PHONY: test test: From 83bb3666bc02231e1270c208af03465a4c80422d Mon Sep 17 00:00:00 2001 From: Shengyu Zhang Date: Thu, 1 Apr 2021 12:51:28 +0800 Subject: [PATCH 09/11] I dont know why we need MANIFEST.in --- MANIFEST.in | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 MANIFEST.in diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 59765f6..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,5 +0,0 @@ -include README.rst -include LICENSE -recursive-include doc * -prune doc/_build -include utils/plugin.zsh From e61079cdf14ae7b61da07036b5bc38e919fb7068 Mon Sep 17 00:00:00 2001 From: Shengyu Zhang Date: Thu, 1 Apr 2021 16:31:12 +0800 Subject: [PATCH 10/11] Find integration files in a correct(?) way --- setup.py | 1 + sphinxnotes/snippet/cli.py | 22 ++++++++++++++----- .../snippet/integration}/plugin.nvim | 0 .../snippet/integration}/plugin.zsh | 0 4 files changed, 17 insertions(+), 6 deletions(-) rename {integration => sphinxnotes/snippet/integration}/plugin.nvim (100%) rename {integration => sphinxnotes/snippet/integration}/plugin.zsh (100%) diff --git a/setup.py b/setup.py index 94d131f..3c153a4 100644 --- a/setup.py +++ b/setup.py @@ -41,6 +41,7 @@ packages=find_namespace_packages(include=['sphinxnotes.*'], exclude=['sphinxnotes.snippet.tests']), include_package_data=True, + package_data={'sphinxnotes.snippet': ['integration/*']}, entry_points={ 'console_scripts': [ 'snippet=sphinxnotes.snippet.cli:main', diff --git a/sphinxnotes/snippet/cli.py b/sphinxnotes/snippet/cli.py index 6b721dc..7bce8bc 100644 --- a/sphinxnotes/snippet/cli.py +++ b/sphinxnotes/snippet/cli.py @@ -19,7 +19,7 @@ from . import __title__, __version__, __description__ from .config import Config from .cache import Cache -from .table import tablify, VISIABLE_COLUMNS +from .table import tablify, COLUMNS DEFAULT_CONFIG_FILE = path.join(xdg_config_home, __title__, 'conf.py') @@ -27,6 +27,16 @@ class HelpFormatter(argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter): pass +def get_integration_file(fn:str) -> str: + """ + Get file path of integration files. + + .. note:: files are included by ``setup(package_data=xxx)`` + """ + prefix = path.abspath(path.dirname(__file__)) + return path.join(prefix, 'integration', fn) + + def main(argv:List[str]=sys.argv[1:]) -> int: """Command line entrypoint.""" @@ -51,8 +61,7 @@ def main(argv:List[str]=sys.argv[1:]) -> int: listparser = subparsers.add_parser('list', aliases=['l'], formatter_class=HelpFormatter, - help='list snippet indexes, columns of indexes: %s' % - VISIABLE_COLUMNS) + help='list snippet indexes, columns of indexes: %s' % COLUMNS) listparser.add_argument('--kinds', '-k', type=str, default='*', help='list specified kinds only') listparser.add_argument('--width', '-w', type=int, @@ -108,6 +117,8 @@ def _on_command_mgmt(args:argparse.Namespace): num_docs = len(cache.num_snippets_by_docid) num_snippets = sum(cache.num_snippets_by_project.values()) print(f'snippets are loaded from {cache.dirname}') + print(f'integration files are located at {get_integration_file("")}') + print('') print(f'I have {num_projects} project(s), {num_docs} documentation(s) and {num_snippets} snippet(s)') for i, v in cache.num_snippets_by_project.items(): print(f'project {i}:') @@ -134,13 +145,12 @@ def _on_command_get(args:argparse.Namespace): def _on_command_integration(args:argparse.Namespace): - # NOTE: files are included by MANIFEST.in if args.zsh: - with open('integration/plugin.zsh', 'r') as f: + with open(get_integration_file('plugin.zsh'), 'r') as f: print(f.read()) return if args.nvim: - with open('integration/plugin.nvim', 'r') as f: + with open(get_integration_file('plugin.nvim'), 'r') as f: print(f.read()) return args.parser.print_help() diff --git a/integration/plugin.nvim b/sphinxnotes/snippet/integration/plugin.nvim similarity index 100% rename from integration/plugin.nvim rename to sphinxnotes/snippet/integration/plugin.nvim diff --git a/integration/plugin.zsh b/sphinxnotes/snippet/integration/plugin.zsh similarity index 100% rename from integration/plugin.zsh rename to sphinxnotes/snippet/integration/plugin.zsh From 3378dadd886d7b37297a2b8e8b2c39a42b0e3b6a Mon Sep 17 00:00:00 2001 From: Shengyu Zhang Date: Thu, 1 Apr 2021 17:04:06 +0800 Subject: [PATCH 11/11] Minor fixes --- Makefile | 2 +- sphinxnotes/snippet/integration/plugin.nvim | 1 + sphinxnotes/snippet/integration/plugin.zsh | 4 +++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f6fd3ca..a726101 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ upload: dist/ $(PY) -m twine upload --repository pypi $<* .PHONY: install -install: +install: dist $(PY) -m pip install --user --no-deps --force-reinstall dist/*.whl .PHONY: test diff --git a/sphinxnotes/snippet/integration/plugin.nvim b/sphinxnotes/snippet/integration/plugin.nvim index 8f8bffe..88d9815 100644 --- a/sphinxnotes/snippet/integration/plugin.nvim +++ b/sphinxnotes/snippet/integration/plugin.nvim @@ -4,6 +4,7 @@ " :Author: Shengyu Zhang " :Date: 2021-04-01 " :License: BSD +" :Version: 20210401 " " NOTE: junegunn/fzf.vim is required " diff --git a/sphinxnotes/snippet/integration/plugin.zsh b/sphinxnotes/snippet/integration/plugin.zsh index 08f82e8..5d5694c 100644 --- a/sphinxnotes/snippet/integration/plugin.zsh +++ b/sphinxnotes/snippet/integration/plugin.zsh @@ -4,6 +4,7 @@ # :Author: Shengyu Zhang # :Date: 2021-03-20 # :License: BSD +# :Version: 20210401 # # The recommanded key bindings are:: # @@ -24,7 +25,8 @@ function snippet_view() { } function snippet_edit() { - $EDITOR $($snippet get --file $(snippet_list dc)) + BUFFER="$BUFFER $EDITOR $($snippet get --file $(snippet_list dc))" + zle accept-line } # Define a widget, mapped to our function above.