From 43951e5851113dc43665446c300490a74375694d Mon Sep 17 00:00:00 2001 From: Tinmarino Date: Tue, 16 Jun 2020 13:46:25 -0400 Subject: [PATCH] Clean & Fix: cycle_bullets bug not defined key in dic: #911 --- autoload/vimwiki/lst.vim | 41 +++++---- autoload/vimwiki/vars.vim | 116 +++++++++++++++++++++----- doc/vimwiki.txt | 12 ++- syntax/vimwiki_markdown.vim | 3 +- test/independent_runs/map.vader | 88 +++++++++++++++---- test/vader_includes/vader_setup.vader | 14 +++- 6 files changed, 219 insertions(+), 55 deletions(-) diff --git a/autoload/vimwiki/lst.vim b/autoload/vimwiki/lst.vim index 0e72e54..4697e56 100644 --- a/autoload/vimwiki/lst.vim +++ b/autoload/vimwiki/lst.vim @@ -180,26 +180,32 @@ endfunction "Returns: the mainly used data structure in this file "An item represents a single list item and is a dictionary with the keys "lnum - the line number of the list item -"type - 1 for bulleted item, 2 for numbered item, 0 for a regular line -"mrkr - the concrete marker, e.g. '**' or 'b)' +"type - 1 for bulleted item, 2 for numbered item, 0 for a regular line (default) +"mrkr - the concrete marker, e.g. '**' or 'b)' (default '') "cb - the char in the checkbox or '' if there is no checkbox function! s:get_item(lnum) abort + " Init default let item = {'lnum': a:lnum} + let item.type = 0 + let item.mrkr = '' + let item.cb = '' + + " Clause: Check lnum argument is in buffer line range if a:lnum == 0 || a:lnum > line('$') - let item.type = 0 return item endif + " Search for list on current line let matches = matchlist(getline(a:lnum), vimwiki#vars#get_wikilocal('rxListItem')) + " Clause: If not on a list line => do not work if matches == [] || \ (matches[1] ==? '' && matches[2] ==? '') || \ (matches[1] !=? '' && matches[2] !=? '') - let item.type = 0 return item endif + " Fill item let item.cb = matches[3] - if matches[1] !=? '' let item.type = 1 let item.mrkr = matches[1] @@ -208,6 +214,7 @@ function! s:get_item(lnum) abort let item.mrkr = matches[2] endif + " See you on an other stack return item endfunction @@ -1257,22 +1264,26 @@ function! s:increase_level(item, by) abort call s:indent_cycle_bullets(a:item, a:by) endfunction -" s:indent_cycle_bullets cycles through the bullet list markers set in + +" Cycle through the bullet list markers set in " `bullet_types` based on the indentation level " TODO there is potential to merge this with the change_marker* funcs further " up if we can make them operate on arbitrary lists of characters function! s:indent_cycle_bullets(item, indent_by) abort - if vimwiki#vars#get_syntaxlocal('cycle_bullets') && a:item.type == 1 - let bullets = vimwiki#vars#get_syntaxlocal('bullet_types') - let i = index(bullets, s:first_char(a:item.mrkr)) + a:indent_by - " calculate the index in a way that wraps around the end of the list - " making it behave like a ring buffer - let new_mrkr = bullets[((i % len(bullets) + len(bullets)) % len(bullets))] - call vimwiki#lst#change_marker(a:item.lnum, a:item.lnum, new_mrkr, 'n') + " Clause: Check if should work + if !vimwiki#vars#get_syntaxlocal('cycle_bullets') || a:item.type != 1 + return endif + let bullets = vimwiki#vars#get_syntaxlocal('bullet_types') + let i = index(bullets, s:first_char(a:item.mrkr)) + a:indent_by + " Calculate the index in a way that wraps around the end of the list + " ... making it behave like a ring buffer + let new_mrkr = bullets[((i % len(bullets) + len(bullets)) % len(bullets))] + call vimwiki#lst#change_marker(a:item.lnum, a:item.lnum, new_mrkr, 'n') endfunction -"adds a:indent_by to the current indent + +" Add a:indent_by to the current indent "a:indent_by can be negative function! s:indent_line_by(lnum, indent_by) abort let item = s:get_item(a:lnum) @@ -1285,7 +1296,7 @@ function! s:indent_line_by(lnum, indent_by) abort endfunction -"changes lvl of lines in selection +" Change lvl of lines in selection function! s:change_level(from_line, to_line, direction, plus_children) abort let from_item = s:get_corresponding_item(a:from_line) if from_item.type == 0 diff --git a/autoload/vimwiki/vars.vim b/autoload/vimwiki/vars.vim index 3b0fc78..953b119 100644 --- a/autoload/vimwiki/vars.vim +++ b/autoload/vimwiki/vars.vim @@ -26,7 +26,23 @@ " variables, not the underlying dicts! " ------------------------------------------------------------------------------------------------ +" Script variable +let s:margin_set_by_user = 0 + +" Helper, Init global and local variables +function! vimwiki#vars#init() abort + call s:populate_global_variables() + call s:populate_wikilocal_options() +endfunction + + +" ---------------------------------------------------------- +" 1. Global +" ---------------------------------------------------------- + +" Populate global variable <- user & default +" Called: s:vimwiki#vars#init function! s:populate_global_variables() abort let g:vimwiki_global_vars = {} @@ -140,6 +156,8 @@ function! s:populate_global_variables() abort endfunction +" Read user global settings +" Called: s:populate_global_variables function! s:read_global_settings_from_user() abort let global_settings = { \ 'CJK_length': {'type': type(0), 'default': 0, 'min': 0, 'max': 1}, @@ -244,6 +262,8 @@ function! s:read_global_settings_from_user() abort endfunction +" Normalize user global settings +" Called: s:populate_global_variables function! s:normalize_global_settings() abort let keys = keys(g:vimwiki_global_vars.ext2syntax) for ext in keys @@ -321,8 +341,17 @@ function! s:normalize_global_settings() abort endfunction -let s:margin_set_by_user = 0 +" ---------------------------------------------------------- +" 2. Buffer local +" ---------------------------------------------------------- + +" Populate local variable <- user & default +" Called: s:vimwiki#vars#init function! s:populate_wikilocal_options() abort + " Init local variable container + let g:vimwiki_wikilocal_vars = [] + + " Declare default values let default_values = { \ 'auto_diary_index': {'type': type(0), 'default': 0, 'min': 0, 'max': 1}, \ 'auto_export': {'type': type(0), 'default': 0, 'min': 0, 'max': 1}, @@ -356,12 +385,12 @@ function! s:populate_wikilocal_options() abort \ 'template_path': {'type': type(''), 'default': $HOME . '/vimwiki/templates/'}, \ 'html_filename_parameterization': {'type': type(0), 'default': 0, 'min': 0, 'max': 1}, \ 'bullet_types': {'type': type([]), 'default': []}, + \ 'cycle_bullets': {'type': type(0), 'default': 0}, \ 'listsyms': {'type': type(''), 'default': vimwiki#vars#get_global('listsyms')}, \ 'listsym_rejected': {'type': type(''), 'default': vimwiki#vars#get_global('listsym_rejected')}, \ } - let g:vimwiki_wikilocal_vars = [] - + " Fill default setting <- user or plugin values let default_wiki_settings = {} for key in keys(default_values) if exists('g:vimwiki_'.key) @@ -372,7 +401,7 @@ function! s:populate_wikilocal_options() abort endif endfor - " set the wiki-local variables according to g:vimwiki_list (or the default settings) + " Set the wiki-local variables according to g:vimwiki_list (or the default settings) if exists('g:vimwiki_list') for users_wiki_settings in g:vimwiki_list let new_wiki_settings = {} @@ -408,10 +437,10 @@ function! s:populate_wikilocal_options() abort if len(wiki.bullet_types) == 0 let wiki.bullet_types = vimwiki#vars#get_syntaxlocal('bullet_types', wiki.syntax) endif - call vimwiki#vars#populate_list_vars(wiki) + call s:populate_list_vars(wiki) endfor - " check some values individually + " Check some values individually let key = 'nested_syntaxes' for wiki_settings in g:vimwiki_wikilocal_vars let users_value = wiki_settings[key] @@ -429,6 +458,12 @@ function! s:populate_wikilocal_options() abort endfunction +" Helper, Check user setting +" warn user with echo message if not good type +" Param: 1: key : varaible name +" Param: 2: vimwiki_key : user value +" Param: 3: value_infod : type and default value +" Param: 4: coming from a global variable function! s:check_users_value(key, users_value, value_infos, comes_from_global_variable) abort let type_code_to_name = { \ type(0): 'number', @@ -487,6 +522,7 @@ function! s:check_users_value(key, users_value, value_infos, comes_from_global_v endfunction +" Normalize local settings function! s:normalize_wikilocal_settings() abort for wiki_settings in g:vimwiki_wikilocal_vars let wiki_settings['path'] = s:normalize_path(wiki_settings['path']) @@ -520,6 +556,7 @@ function! s:normalize_wikilocal_settings() abort endfunction +" Helper path " TODO move to path function! s:normalize_path(path) abort " trim trailing / and \ because otherwise resolve() doesn't work quite right @@ -532,20 +569,39 @@ function! s:normalize_path(path) abort endfunction +" ---------------------------------------------------------- +" 3. Syntax specific +" ---------------------------------------------------------- + +" Populate syntax variable +" Exported: syntax/vimwiki.vim function! vimwiki#vars#populate_syntax_vars(syntax) abort + " Create is not exists if !exists('g:vimwiki_syntax_variables') let g:vimwiki_syntax_variables = {} endif + " Clause: leave if already filled if has_key(g:vimwiki_syntax_variables, a:syntax) return endif + " Init syntax variable dictionary let g:vimwiki_syntax_variables[a:syntax] = {} + " Autoload default syntax file execute 'runtime! syntax/vimwiki_'.a:syntax.'.vim' - " generic stuff + " TODO make that clean (i.e clearify what is local to syntax ot to buffer) + " Get from local vars + let bullet_types = vimwiki#vars#get_wikilocal('bullet_types') + if !empty(bullet_types) + let g:vimwiki_syntax_variables[a:syntax]['bullet_types'] = bullet_types + endif + let g:vimwiki_syntax_variables[a:syntax]['cycle_bullets'] = + \ vimwiki#vars#get_wikilocal('cycle_bullets') + + " Populate generic stuff let header_symbol = g:vimwiki_syntax_variables[a:syntax].rxH if g:vimwiki_syntax_variables[a:syntax].symH " symmetric headers @@ -605,7 +661,7 @@ function! vimwiki#vars#populate_syntax_vars(syntax) abort let char_to_rx = {'1': '\d\+', 'i': '[ivxlcdm]\+', 'I': '[IVXLCDM]\+', \ 'a': '\l\{1,2}', 'A': '\u\{1,2}'} - "create regexp for bulleted list items + " Create regexp for bulleted list items if !empty(g:vimwiki_syntax_variables[a:syntax].bullet_types) let g:vimwiki_syntax_variables[a:syntax].rxListBullet = \ join( map(copy(g:vimwiki_syntax_variables[a:syntax].bullet_types), @@ -617,7 +673,7 @@ function! vimwiki#vars#populate_syntax_vars(syntax) abort let g:vimwiki_syntax_variables[a:syntax].rxListBullet = '$^' endif - "create regex for numbered list items + " Create regex for numbered list items if !empty(g:vimwiki_syntax_variables[a:syntax].number_types) let g:vimwiki_syntax_variables[a:syntax].rxListNumber = '\C\%(' for type in g:vimwiki_syntax_variables[a:syntax].number_types[:-2] @@ -674,13 +730,16 @@ function! vimwiki#vars#populate_syntax_vars(syntax) abort \ . g:vimwiki_global_vars.rxWikiLinkDescr. '\ze\)\?' \ . g:vimwiki_global_vars.rx_wikilink_suffix + " Work more if markdown if a:syntax ==# 'markdown' call s:populate_extra_markdown_vars() endif endfunction -function! vimwiki#vars#populate_list_vars(wiki) abort +" Populate list variable +" or how to search and treat list (ex: *,-, 1.) +function! s:populate_list_vars(wiki) abort let syntax = a:wiki.syntax let a:wiki.rx_bullet_char = '['.escape(join(a:wiki.bullet_types, ''), ']^-\').']' @@ -693,7 +752,7 @@ function! vimwiki#vars#populate_list_vars(wiki) abort \ recurring_bullets \ ? a:wiki.bullet_types : [] - "create regexp for bulleted list items + " Create regexp for bulleted list items if !empty(a:wiki.bullet_types) let rxListBullet = \ join( map(copy(a:wiki.bullet_types), @@ -705,7 +764,7 @@ function! vimwiki#vars#populate_list_vars(wiki) abort let rxListBullet = '$^' endif - "the user can set the listsyms as string, but vimwiki needs a list + " the user can set the listsyms as string, but vimwiki needs a list let a:wiki.listsyms_list = split(a:wiki.listsyms, '\zs') if match(a:wiki.listsyms, a:wiki.listsym_rejected) != -1 @@ -737,8 +796,7 @@ function! vimwiki#vars#populate_list_vars(wiki) abort endfunction - - +" Populate markdown specific syntax variables function! s:populate_extra_markdown_vars() abort let mkd_syntax = g:vimwiki_syntax_variables['markdown'] @@ -908,27 +966,33 @@ function! s:populate_extra_markdown_vars() abort endfunction -function! vimwiki#vars#init() abort - call s:populate_global_variables() - call s:populate_wikilocal_options() -endfunction - +" ---------------------------------------------------------- +" 4. Getter, Setter (exported) +" ---------------------------------------------------------- +" Get syntax variable +" Param: 1: key () +" Param: (2): syntax name ( ex:'markdown') function! vimwiki#vars#get_syntaxlocal(key, ...) abort + " Retrieve desired syntax name if a:0 let syntax = a:1 else let syntax = vimwiki#vars#get_wikilocal('syntax') endif + + " Create syntax varaible dict if not exists (lazy) if !exists('g:vimwiki_syntax_variables') || !has_key(g:vimwiki_syntax_variables, syntax) call vimwiki#vars#populate_syntax_vars(syntax) endif + " Return d_syntax[a:key] return g:vimwiki_syntax_variables[syntax][a:key] endfunction -" Get a variable for the buffer we are currently in or for the given buffer (number or name). +" Return: buffer local variable +" for the buffer we are currently in or for the given buffer (number or name). " Populate the variable, if it doesn't exist. function! vimwiki#vars#get_bufferlocal(key, ...) abort let buffer = a:0 ? a:1 : '%' @@ -962,24 +1026,29 @@ function! vimwiki#vars#get_bufferlocal(key, ...) abort endfunction +" Set buffer local variable function! vimwiki#vars#set_bufferlocal(key, value, ...) abort let buffer = a:0 ? a:1 : '%' call setbufvar(buffer, 'vimwiki_' . a:key, a:value) endfunction +" Return: wiki global variable function! vimwiki#vars#get_global(key) abort return g:vimwiki_global_vars[a:key] endfunction +" Set global variable function! vimwiki#vars#set_global(key, value) abort let g:vimwiki_global_vars[a:key] = a:value return g:vimwiki_global_vars[a:key] endfunction -" the second argument can be a wiki number. When absent, the wiki of the currently active buffer is +" Return: wiki local named varaible +" Param: 1: variable name (alias key, ) +" Param: (2): wiki number (). When absent, the wiki of the currently active buffer is " used function! vimwiki#vars#get_wikilocal(key, ...) abort if a:0 @@ -990,11 +1059,13 @@ function! vimwiki#vars#get_wikilocal(key, ...) abort endfunction +" Return: wiki local variable (of default wiki [index -1]) function! vimwiki#vars#get_wikilocal_default(key) abort return g:vimwiki_wikilocal_vars[-1][a:key] endfunction +" Set local variable function! vimwiki#vars#set_wikilocal(key, value, wiki_nr) abort if a:wiki_nr == len(g:vimwiki_wikilocal_vars) - 1 call insert(g:vimwiki_wikilocal_vars, {}, -1) @@ -1003,6 +1074,7 @@ function! vimwiki#vars#set_wikilocal(key, value, wiki_nr) abort endfunction +" Append new wiki to wiki list function! vimwiki#vars#add_temporary_wiki(settings) abort let new_temp_wiki_settings = copy(g:vimwiki_wikilocal_vars[-1]) for [key, value] in items(a:settings) @@ -1013,7 +1085,7 @@ function! vimwiki#vars#add_temporary_wiki(settings) abort endfunction -" number of registered wikis + temporary +" Return: number of registered wikis + temporary function! vimwiki#vars#number_of_wikis() abort return len(g:vimwiki_wikilocal_vars) - 1 endfunction diff --git a/doc/vimwiki.txt b/doc/vimwiki.txt index b8d960f..c9e64ee 100644 --- a/doc/vimwiki.txt +++ b/doc/vimwiki.txt @@ -2522,7 +2522,7 @@ Note: if you use Markdown or MediaWiki syntax, you probably would like to set this option to 0, because every indented line is considered verbatim text. -*vimwiki-bullet_types* +*vimwiki-option-bullet_types* ------------------------------------------------------------------------------ Key Default value~ bullet_types ['-', '*', '#'] (default-syntax) @@ -2537,6 +2537,15 @@ You can set it to include more fancy symbols like this: let g:vimwiki_list = [{'path': '~/path/', 'bullet_types' = ['-', '•', '→']}] +*vimwiki-option-bullet_types* +------------------------------------------------------------------------------ +Key Default value~ +cycle_bullets 0 + +If set to 1 (true), cycle through |bullet_types| when changing list element +identation + + *vimwiki-listsyms* ------------------------------------------------------------------------------ Key Default value~ @@ -3596,6 +3605,7 @@ http://code.google.com/p/vimwiki/issues/list. They may be accessible from https://github.com/vimwiki-backup/vimwiki/issues. New:~ + * PR #907: Cycle bullets * PR #900: conceallevel is now setted locally for vimwiki buffers 2.5 (2020-05-26)~ diff --git a/syntax/vimwiki_markdown.vim b/syntax/vimwiki_markdown.vim index ec811fb..b0849e1 100644 --- a/syntax/vimwiki_markdown.vim +++ b/syntax/vimwiki_markdown.vim @@ -73,12 +73,11 @@ let s:markdown_syntax.rxHR = '\(^---*$\|^___*$\|^\*\*\**$\)' let s:markdown_syntax.rxTableSep = '|' " Lists -let s:markdown_syntax.bullet_types = ['*', '-', '+'] let s:markdown_syntax.recurring_bullets = 0 -let s:markdown_syntax.cycle_bullets = 1 let s:markdown_syntax.number_types = ['1.'] let s:markdown_syntax.list_markers = ['-', '*', '+', '1.'] let s:markdown_syntax.rxListDefine = '::\%(\s\|$\)' +let s:markdown_syntax.bullet_types = ['*', '-', '+'] " Preformatted text (code blocks) let s:markdown_syntax.rxPreStart = '\%(`\{3,}\|\~\{3,}\)' diff --git a/test/independent_runs/map.vader b/test/independent_runs/map.vader index c99d6f9..21474a5 100644 --- a/test/independent_runs/map.vader +++ b/test/independent_runs/map.vader @@ -8,18 +8,6 @@ Execute (Configure: Set vimwiki list to markdown resource): Log "Let mapleader = ," let mapleader = ',' - Log "Declare function DestroyVar" - function! DestroyVar(var) - if ! exists(a:var) | return | endif - execute "unlet " . a:var - endfunction - - Log "Declare function AssertTab" - function! AssertTab(nr) - " Vader is creating 2 tabs - AssertEqual a:nr + 2, tabpagenr() - endfunction - Log "Destroy vimrc or previous run heritage" call DestroyVar('g:vimwiki_list') call DestroyVar('g:vimwiki_global_vars') @@ -380,6 +368,23 @@ Expect (Renumber): 1. Much 3. You + +# New launch +# +Given (Number list): + 1. I + 1. Relly + 2. Love + 1. Very + 1. Much + 3. You + +Execute (file .md): + file toto.md + edit! + AssertEqual 'vimwiki', &ft + set sw=2 + Do (gl*): gl* @@ -402,6 +407,8 @@ Expect (list -> *): 1. Much * You +# New launch +# Given (Bulleted list): * I - Relly @@ -411,12 +418,14 @@ Given (Bulleted list): * You Execute (file .md): + set sw=2 file toto.md edit! + let g:vimwiki_syntax_variables['markdown']['cycle_bullets'] = 1 + let g:vimwiki_syntax_variables['markdown']['bullet_types'] = ['*', '-', '+'] AssertEqual 'vimwiki', &ft - set sw=2 -Do (2gll): +Do (gLl): gLl Expect (Increase): @@ -452,6 +461,57 @@ Expect (New item): - Much - + +# New launch +# +Given (List ->): + * Item1 + +Execute (file toto.md): + " Note: let s:markdown_syntax.bullet_types = ['*', '-', '+'] + file toto.md + edit! + Log "Cycle bullets" + let g:vimwiki_syntax_variables['bullet_types'] = ['*', '-'] + let g:vimwiki_syntax_variables['markdown']['cycle_bullets'] = 1 + AssertEqual g:vimwiki_syntax_variables['markdown']['cycle_bullets'], 1 + AssertEqual 'vimwiki', &ft + set sw=2 + set expandtab " Otherwise, getting some tab before some items, when enought space + +Do (o): + oItem2 + +Expect (Good bullet type): + * Item1 + * Item2 + +# TODO test more, (see real cycle, but do not work with low vim) +Do (o + ): + o2 + \\ + o3 + \\ + +Expect (Good bullet type): + * Item1 + - 2 + + 3 + +Do (o + ): + A1\ + 2\\ + 3\ + +Expect (Good nested bullet type): + * Item11 + - 2 + + 3 + + +# TODO test: let g:vimwiki_bullet_types = ['-', '•', '→', '*'] + + # 3 Text Object {{{1 #################### diff --git a/test/vader_includes/vader_setup.vader b/test/vader_includes/vader_setup.vader index 65b3535..11f1770 100644 --- a/test/vader_includes/vader_setup.vader +++ b/test/vader_includes/vader_setup.vader @@ -74,7 +74,7 @@ Before (Define functions): write % endfunction - " print a command output to the buffer + " Print a command output to the buffer function! PrintCommand(cmd) redir => message silent execute a:cmd @@ -86,4 +86,16 @@ Before (Define functions): endif endfunction + " Destroy a variable is exists (unlet) + function! DestroyVar(var) + if ! exists(a:var) | return | endif + execute "unlet " . a:var + endfunction + + " Assert current tab is desired tab + function! AssertTab(nr) + " Vader is creating 2 tabs + AssertEqual a:nr + 2, tabpagenr() + endfunction + # vim: ft=vim