commit ac38bb2f09f49b287ed8f59e0518b56dceadd6cc
parent edf562fab015c4e2b5322339f0c63f3c23cb0977
Author: Tinmarino <tinmarino@gmail.com>
Date: Fri, 24 Jul 2020 17:59:54 -0400
Refactor: normalize_link_v, creating u#get_selection (Fix #382)
* Less hacky selection handling: nomal command hack -> vimscript code
* Some prettifying, antipattern removal
Diffstat:
4 files changed, 184 insertions(+), 93 deletions(-)
diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim
@@ -2380,50 +2380,55 @@ endfunction
" TODO mutualize most code with syntax_n
" Normalize link in visual mode Enter keypress
function! s:normalize_link_syntax_v() abort
- let sel_save = &selection
- let &selection = 'old'
- let default_register_save = @"
- let registertype_save = getregtype('"')
+ " Get selection content
+ let visual_selection = vimwiki#u#get_selection()
- try
- " Save selected text to register "
- normal! gv""y
-
- " Set substitution
- " Replace Url
- if vimwiki#base#is_diary_file(expand('%:p'))
- let sub = vimwiki#base#normalize_link_in_diary(@")
+ " Embed link in template
+ " In case of a diary link, wiki or markdown link
+ if vimwiki#base#is_diary_file(expand('%:p'))
+ let link = vimwiki#base#normalize_link_in_diary(visual_selection)
+ else
+ " Warning nested syntax discrimination
+ if vimwiki#vars#get_wikilocal('syntax') ==# 'markdown'
+ let template = vimwiki#vars#get_syntaxlocal('Weblink1Template')
else
- let sub = s:safesubstitute(vimwiki#vars#get_global('WikiLinkTemplate1'),
- \ '__LinkUrl__', @", '')
+ let template = vimwiki#vars#get_global('WikiLinkTemplate1')
endif
- " Replace file extension
- let file_extension = vimwiki#vars#get_wikilocal('ext', vimwiki#vars#get_bufferlocal('wiki_nr'))
- let sub = s:safesubstitute(sub, '__FileExtension__', file_extension , '')
+ let link = s:safesubstitute(template, '__LinkUrl__', visual_selection, '')
+ endif
- " Put substitution in register " and change text
- let sc = vimwiki#vars#get_wikilocal('links_space_char')
- call setreg('"', substitute(substitute(sub, '\n', '', ''), '\s', sc, 'g'), visualmode())
- normal! `>""pgvd
- finally
- call setreg('"', default_register_save, registertype_save)
- let &selection = sel_save
- endtry
+ " Transform link:
+ " Replace description (used for markdown)
+ let link = s:safesubstitute(link, '__LinkDescription__', visual_selection, '')
+ " Replace file extension
+ let file_extension = vimwiki#vars#get_wikilocal('ext', vimwiki#vars#get_bufferlocal('wiki_nr'))
+ let link = s:safesubstitute(link, '__FileExtension__', file_extension , '')
+ " Replace space characters
+ let sc = vimwiki#vars#get_wikilocal('links_space_char')
+ let link = substitute(link, '\s', sc, 'g')
+ " Remove newlines
+ let link = substitute(link, '\n', '', '')
+
+ " Paste result
+ call vimwiki#u#get_selection(link)
endfunction
" Normalize link
function! vimwiki#base#normalize_link(is_visual_mode) abort
- if exists('*vimwiki#'.vimwiki#vars#get_wikilocal('syntax').'_base#normalize_link')
- " Syntax-specific links
- call vimwiki#{vimwiki#vars#get_wikilocal('syntax')}_base#normalize_link(a:is_visual_mode)
+ " Switch implementation
+ " If visual mode
+ " TODO elseif line("'<") == line("'>")
+ if a:is_visual_mode
+ return s:normalize_link_syntax_v()
+
+ " If Syntax-specific normalizer exists: call it
+ elseif exists('*vimwiki#'.vimwiki#vars#get_wikilocal('syntax').'_base#normalize_link')
+ return vimwiki#{vimwiki#vars#get_wikilocal('syntax')}_base#normalize_link()
+
+ " Normal mode default
else
- if !a:is_visual_mode
- call s:normalize_link_syntax_n()
- elseif line("'<") == line("'>")
- " action undefined for multi-line visual mode selections
- call s:normalize_link_syntax_v()
- endif
+ return s:normalize_link_syntax_n()
endif
endfunction
diff --git a/autoload/vimwiki/markdown_base.vim b/autoload/vimwiki/markdown_base.vim
@@ -111,55 +111,7 @@ function! s:normalize_link_syntax_n() abort
endfunction
-function! s:normalize_link_syntax_v() abort
- let lnum = line('.')
- let sel_save = &selection
- let &selection = 'old'
- let rv = @"
- let rt = getregtype('"')
- let done = 0
-
- try
- norm! gvy
- let visual_selection = @"
-
- if vimwiki#base#is_diary_file(expand('%:p'))
- let link = vimwiki#base#normalize_link_in_diary(visual_selection)
- else
- let link = s:safesubstitute(vimwiki#vars#get_syntaxlocal('Weblink1Template'),
- \ '__LinkUrl__', visual_selection, '')
- endif
-
- " Replace spaces with new character if option is set
- let link = substitute(link, '\s', vimwiki#vars#get_wikilocal('links_space_char'), 'g')
-
- " Replace description
- let link = s:safesubstitute(link, '__LinkDescription__', visual_selection, '')
-
- " Replace file extension
- let file_extension = vimwiki#vars#get_wikilocal('ext', vimwiki#vars#get_bufferlocal('wiki_nr'))
- let link = s:safesubstitute(link, '__FileExtension__', file_extension , '')
-
- call setreg('"', substitute(link, '\n', '', ''), visualmode())
-
- " paste result
- norm! `>""pgvd
-
- finally
- call setreg('"', rv, rt)
- let &selection = sel_save
- endtry
-
-endfunction
-
-
-function! vimwiki#markdown_base#normalize_link(is_visual_mode) abort
-
- if !a:is_visual_mode
- call s:normalize_link_syntax_n()
- elseif line("'<") == line("'>")
- " action undefined for multi-line visual mode selections
- call s:normalize_link_syntax_v()
- endif
+function! vimwiki#markdown_base#normalize_link() abort
+ " TODO mutualize with base
+ call s:normalize_link_syntax_n()
endfunction
-
diff --git a/autoload/vimwiki/u.vim b/autoload/vimwiki/u.vim
@@ -4,6 +4,55 @@
" Home: https://github.com/vimwiki/vimwiki/
+" Get visual selection text content, optionaly replace its content
+" :param: Text to replace selection
+function! vimwiki#u#get_selection(...) abort
+ " Copyed from DarkWiiPlayer at stackoverflow
+ " https://stackoverflow.com/a/47051271/2544873
+ " Get selection extremity position,
+ " Discriminate selection mode
+ if mode() ==? 'v'
+ let [line_start, column_start] = getpos('v')[1:2]
+ let [line_end, column_end] = getpos('.')[1:2]
+ else
+ let [line_start, column_start] = getpos("'<")[1:2]
+ let [line_end, column_end] = getpos("'>")[1:2]
+ end
+
+ " Guard
+ if (line2byte(line_start)+column_start) > (line2byte(line_end)+column_end)
+ let [line_start, column_start, line_end, column_end] =
+ \ [line_end, column_end, line_start, column_start]
+ end
+ let lines = getline(line_start, line_end)
+ if len(lines) == 0
+ return ''
+ endif
+
+ " If want to modify selection
+ if a:0 > 0
+ " Grab new content
+ let line_link = a:1
+
+ " Grab the content of line around the link: pre and post
+ let start_link = max([column_start - 2, 0])
+ let line_pre = ''
+ if start_link > 0
+ let line_pre .= lines[0][ : start_link]
+ endif
+ let line_post = lines[0][column_end - (&selection ==# 'inclusive' ? 0 : 1) : ]
+
+ " Set the only single selected line
+ call setline(line_start, line_pre . line_link . line_post)
+ endif
+
+ " Get selection extremity position, take into account selection option
+ let lines[-1] = lines[-1][: column_end - (&selection ==# 'inclusive' ? 1 : 2)]
+ let lines[0] = lines[0][column_start - 1:]
+ return join(lines, "\n")
+endfunction
+
+
" Execute: string v:count times
function! vimwiki#u#count_exe(cmd) abort
for i in range( max([1, v:count]) )
@@ -12,6 +61,7 @@ function! vimwiki#u#count_exe(cmd) abort
endfunction
+" Trim spaces: leading and trailing
function! vimwiki#u#trim(string, ...) abort
let chars = ''
if a:0 > 0
@@ -42,11 +92,13 @@ function! vimwiki#u#os_name() abort
endfunction
+" Check if OS is windows
function! vimwiki#u#is_windows() abort
return has('win32') || has('win64') || has('win95') || has('win16')
endfunction
+" Check if OS is mac
function! vimwiki#u#is_macos() abort
if has('mac') || has('macunix') || has('gui_mac')
return 1
@@ -81,15 +133,13 @@ endfunction
" Backward compatible version of the built-in function shiftwidth()
-if exists('*shiftwidth')
- function! vimwiki#u#sw() abort
+function! vimwiki#u#sw() abort
+ if exists('*shiftwidth')
return shiftwidth()
- endfunc
-else
- function! vimwiki#u#sw() abort
+ else
return &shiftwidth
- endfunc
-endif
+ endif
+endfunc
" a:mode single character indicating the mode as defined by :h maparg
" a:key the key sequence to map
@@ -116,7 +166,7 @@ function! vimwiki#u#map_key(mode, key, plug, ...) abort
endfunction
-" returns 1 if line is a code block or math block
+" Returns: 1 if line is a code block or math block
"
" The last two conditions are needed for this to correctly
" detect nested syntaxes within code blocks
diff --git a/test/link_creation.vader b/test/link_creation.vader
@@ -1,5 +1,89 @@
Include: vader_includes/vader_setup.vader
+# Visual Creatin {{{1
+# Issues: #382
+####################
+
+Execute (Log):
+ Log 'Visual Creation'
+
+# For markdown {{{2
+# ------------------
+
+Given vimwiki (abc def ghi jkl):
+ abc def ghi jkl
+
+Execute (Set filename wiki_test.md):
+ Log '>> Visual creation, markdown syntax'
+ file wiki_test.md
+ call SetSyntax('markdown')
+ AssertEqual vimwiki#vars#get_wikilocal('syntax'), 'markdown'
+
+Do (v3e):
+ v3e\<Cr>
+
+Expect (3 Words []()):
+ [abc def ghi](abc def ghi) jkl
+
+Do (v3e):
+ wv2e\<Cr>
+
+Expect (2 Words []()):
+ abc [def ghi](def ghi) jkl
+
+Do (selection=exclusive v3e):
+ :set selection=exclusive\<Cr>
+ wv2e\<Cr>
+
+Expect (2 Words []()):
+ abc [def ghi](def ghi) jkl
+
+Do (selection=exclusive wv$):
+ :set selection=exclusive\<Cr>
+ wv$\<Cr>
+
+Expect (3 Words []()):
+ abc [def ghi jkl](def ghi jkl)
+
+
+# For Wiki {{{2
+# ------------------
+
+Given vimwiki (abc def ghi jkl):
+ abc def ghi jkl
+
+Execute (Set filename wiki_test.md):
+ Log '>> Visual creation, wiki syntax'
+ file wiki_test.wiki
+ call SetSyntax('default')
+
+Do (v3e):
+ v3e\<Cr>
+
+Expect (3 Words []()):
+ [[abc def ghi]] jkl
+
+Do (v3e):
+ wv2e\<Cr>
+
+Expect (2 Words []()):
+ abc [[def ghi]] jkl
+
+Do (selection=exclusive v3e):
+ :set selection=exclusive\<Cr>
+ wv2e\<Cr>
+
+Expect (2 Words []()):
+ abc [[def ghi]] jkl
+
+Do (selection=exclusive wv$):
+ :set selection=exclusive\<Cr>
+ wv$\<Cr>
+
+Expect (3 Words []()):
+ abc [[def ghi jkl]]
+
+
# Absolute links {{{1
####################