11" AUTOLOAD FUNCTION LIBRARY FOR VIM-FETCH
2+ let s: cpo = &cpo
3+ set cpo &vim
24
35" Position specs Dictionary:
46let s: specs = {}
@@ -27,23 +29,64 @@ function! s:specs.plan9.parse(file) abort
2729 \ [matchlist (a: file , self .pattern)[1 ]]]
2830endfunction
2931
32+ " Detection methods for buffers that bypass `filereadable()`:
33+ let s: ignore = []
34+
35+ " - non-file buffer types
36+ call add (s: ignore , {})
37+ function ! s: ignore [-1 ].detect (buffer ) abort
38+ return ! empty (getbufvar (a: buffer , ' &buftype' ))
39+ endfunction
40+
41+ " - non-document file types that do not trigger the above
42+ " not needed for: Unite / VimFiler / VimShell / CtrlP / Conque-Shell
43+ call add (s: ignore , {' types' : [' netrw' ]})
44+ function ! s: ignore [-1 ].detect (buffer ) abort
45+ return index (self .types, getbufvar (a: buffer , ' &filetype' )) isnot -1
46+ endfunction
47+
48+ " - redirected buffers
49+ call add (s: ignore , {' bufvars' : [' netrw_lastfile' ]})
50+ function ! s: ignore [-1 ].detect (buffer ) abort
51+ for l: var in self .bufvars
52+ if ! empty (getbufvar (a: buffer , l: var ))
53+ return 1
54+ endif
55+ endfor
56+ return 0
57+ endfunction
58+
3059" Edit {file}, placing the cursor at the line and column indicated by {spec}:
3160" @signature: fetch#edit({file:String}, {spec:String})
32- " @notes: won't work from a |BufReadCmd| event as it does not load non-spec files
61+ " @returns: Boolean indicating if a spec path has been detected and processed
62+ " @notes: - won't work from a |BufReadCmd| event as it doesn't load non-spec'ed files
63+ " - won't work from events fired before the spec'ed file is loaded into
64+ " the buffer (i.e. before '%' is set to the spec'ed file) like |BufNew|
65+ " as it won't be able to wipe the spurious new spec'ed buffer
3366function ! fetch#edit (file , spec) abort
34- let l: spec = get (s: specs , a: spec , {})
67+ " naive early exit on obvious non-matches
68+ if filereadable (a: file ) || match (a: file , s: specs [a: spec ].pattern) is -1
69+ return 0
70+ endif
3571
36- " get spec data if needed, else bail
37- if empty (l: spec ) || filereadable (a: file ) || match (a: file , l: spec .pattern) is -1
38- return
72+ " check for unspec'ed editable file
73+ let [l: file , l: pos ] = s: specs [a: spec ].parse (a: file )
74+ if ! filereadable (l: file )
75+ return 0 " in doubt, end with invalid user input
3976 endif
40- let [l: file , l: pos ] = l: spec .parse (a: file )
41- let l: cmd = ' '
4277
43- " get rid of the spec'ed buffer
78+ " processing setup
79+ let l: pre = ' ' " will be prefixed to edit command
80+
81+ " if current buffer is spec'ed and invalid set it up for wiping
4482 if expand (' %:p' ) is fnamemodify (a: file , ' :p' )
83+ for l: ignore in s: ignore
84+ if l: ignore .detect (bufnr (' %' )) is 1
85+ return 0
86+ endif
87+ endfor
4588 set bufhidden = wipe " avoid issues with |bwipeout|
46- let l: cmd .= ' keepalt ' " don't mess up alternate file on switch
89+ let l: pre .= ' keepalt ' " don't mess up alternate file on switch
4790 endif
4891
4992 " clean up argument list
@@ -54,14 +97,19 @@ function! fetch#edit(file, spec) abort
5497 execute l: argidx .' argadd' fnameescape (l: file )
5598 endif
5699 if index (argv (), l: file ) isnot -1
57- let l: cmd .= ' arg' " set arglist index to edited file
100+ let l: pre .= ' arg' " set arglist index to edited file
58101 endif
59102 endif
60103
61104 " open correct file and place cursor at position spec
62- execute l: cmd .' edit!' fnameescape (l: file )
63- call cursor (max ([l: pos [0 ], 1 ]), max ([get (l: pos , 1 , 0 ), 1 ]))
105+ execute l: pre .' edit!' fnameescape (l: file )
106+ let b: fetch_lastpos = [max ([l: pos [0 ], 1 ]), max ([get (l: pos , 1 , 0 ), 1 ])]
107+ call cursor (b: fetch_lastpos [0 ], b: fetch_lastpos [1 ])
64108 silent ! normal ! zO
109+ return 1
65110endfunction
66111
112+ let &cpo = s: cpo
113+ unlet ! s: cpo
114+
67115" vim:set sw = 2 sts = 2 ts = 2 et fdm = marker fmr = {{{,}}}:
0 commit comments