Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions autoload/esearch/buf.vim
Original file line number Diff line number Diff line change
Expand Up @@ -117,16 +117,6 @@ fu! esearch#buf#rename_qf(name) abort
let w:quickfix_title = a:name
endfu

fu! s:bufdo(bufnr, cmd, bang) abort
let cur_buffer = esearch#buf#stay()
try
exe (bufnr('%') == a:bufnr ? '' : a:bufnr.'bufdo ') . a:cmd . (a:bang ? '!' : '')
return 1
catch | call esearch#util#warn(v:exception) | return 0
finally | call cur_buffer.restore()
endtry
endfu

fu! esearch#buf#import() abort
return copy(s:Buf)
endfu
Expand Down Expand Up @@ -155,6 +145,16 @@ else
endfu
endif

fu! s:Buf.bufdo(cmd, ...) abort dict
let cur_buffer = esearch#buf#stay()
try
exe (bufnr('%') == self.bufnr ? '' : self.bufnr.'bufdo ') . a:cmd . (a:0 && a:1 ? '!' : '')
return 1
catch | call esearch#util#warn(v:exception) | return 0
finally | call cur_buffer.restore()
endtry
endfu

if exists('*nvim_buf_line_count')
fu! s:Buf.oneliner() abort dict
return nvim_buf_line_count(self.bufnr) == 1
Expand All @@ -170,7 +170,7 @@ else
endif

fu! s:Buf.goto() abort dict
exe 'buffer!' self.bufnr
exe 'buffer!' self.bufnr
endfu

fu! s:Buf.getline(lnum) abort dict
Expand All @@ -195,7 +195,7 @@ fu! s:Buf.deleteline(lnum) abort dict
endfu

fu! s:Buf.write(bang) dict abort
return s:bufdo(self.bufnr, 'write', a:bang)
return self.bufdo('write', a:bang)
endfu

fu! s:Buf.open(opener, ...) dict abort
Expand All @@ -204,11 +204,11 @@ fu! s:Buf.open(opener, ...) dict abort
endfu

fu! s:Buf.bdelete(...) dict abort
return s:bufdo(self.bufnr, 'bdelete', get(a:, 1))
return self.bufdo('bdelete', get(a:, 1))
endfu

fu! s:Buf.bwipeout(...) dict abort
return s:bufdo(self.bufnr, 'bwipeout', get(a:, 1))
return self.bufdo('bwipeout', get(a:, 1))
endfu

fu! esearch#buf#stay() abort
Expand All @@ -222,5 +222,5 @@ fu! s:CurrentBufferGuard.new() abort dict
endfu

fu! s:CurrentBufferGuard.restore() abort dict
if self.bufnr != bufnr('') | exe self.bufnr 'buffer!' | endif
if self.bufnr != bufnr('') | noau exe self.bufnr 'buffer!' | endif
endfu
1 change: 1 addition & 0 deletions autoload/esearch/out/win.vim
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ let g:esearch#out#win#filename_re = '^[^ ]'
let g:esearch#out#win#separator_re = '^$'
let g:esearch#out#win#linenr_fmt = ' %3d '
let g:esearch#out#win#entry_fmt = ' %3d %s'
let g:esearch#out#win#entry_with_sign_fmt = ' %s %3d %s'

let g:esearch#out#win#searches_with_stopped_highlights = esearch#cache#expiring#new({'max_age': 120, 'size': 1024})

Expand Down
57 changes: 39 additions & 18 deletions autoload/esearch/out/win/diff.vim
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
let s:Dict = vital#esearch#import('Data.Dict')
let s:by_key = function('esearch#util#by_key')
let s:Dict = vital#esearch#import('Data.Dict')
let s:by_key = function('esearch#util#by_key')
let s:Filepath = vital#esearch#import('System.Filepath')
let s:String = vital#esearch#import('Data.String')

let s:path_separator = s:Filepath.separator()

let s:broken_entry_fmt = 'Unexpected entry format at line %d. Must match /^ (sign)? (line_number) (text)/.'
let s:broken_header_fmt = 'Broken header at line %d.'
let s:unexpected_filename_fmt = 'Unexpected filename at line %d. Each filename must be preceded with a blank line separator.'
let s:unexpected_slash_fmt = 'Unexpected trailing "'.s:path_separator.'" in the filename at line %d. Forgot to insert a basename?'
let s:unexpected_prepend_fmt = 'Unexpected "^" at line %d. Prepended lines must be placed before the base or appended lines.'
let s:unexpected_append_fmt = 'Unexpected "+" at line %d. Appended lines must be placed after the base line.'
let s:duplicate_set_fmt = 'Duplicate line number at line %d.'
Expand All @@ -14,13 +19,13 @@ let s:unexpected_separator_fmt = 'Unexpected blank line parator at line %d.'
let s:unexpected_sign_fmt = 'Unexpected sign at line %d.'

fu! esearch#out#win#diff#do() abort
let stats = {'deleted': 0, 'modified': 0, 'added': 0, 'files': 0}
let stats = {'deleted': 0, 'modified': 0, 'added': 0, 'files': 0, 'renamed': 0}
let diffs = {'by_id': {}, 'stats': stats}
let iter = s:DiffsIterator.new(getline(1, '$'), b:esearch, stats)
while iter.has_next()
let diff = iter.next()

if !empty(diff.edits)
if !empty(diff)
let diffs.by_id[diff.ctx.id] = diff
let stats.files += 1
endif
Expand Down Expand Up @@ -70,11 +75,11 @@ fu! s:DiffsIterator.next_deleted() abort dict
let ctx = self.contexts[id]
let [edits, deleted_lines_a] = [{}, copy(ctx.lines)]
let [begin, lnums_b, texts_b] = [-1, [], []]
return s:Diff.new(self.add_deletes(edits, deleted_lines_a), begin, ctx, lnums_b, texts_b)
return s:Diff.new(self.stats, self.add_deletes(edits, deleted_lines_a), begin, ctx, lnums_b, texts_b)
endfu

fu! s:DiffsIterator.next_modified() abort
let [filename_b, lnum_was, sign_was] = ['', -1, ''] " backtrack one line back
fu! s:DiffsIterator.next_modified() abort dict
let [filename_b, lnum_was, sign_was] = ['', -1, ''] " look one line back
let [edits, deleted_lines_a, begin, lnums_b, texts_b] = [{}, {}, -1, [], []]

while self.wlnum < len(self.lines)
Expand All @@ -83,7 +88,7 @@ fu! s:DiffsIterator.next_modified() abort
if empty(line)
if empty(filename_b) | throw s:err(s:unexpected_separator_fmt, self.wlnum) | endif
let self.wlnum += 1
return s:Diff.new(self.add_deletes(edits, deleted_lines_a), begin, ctx, lnums_b, texts_b)
return s:Diff.new(self.stats, self.add_deletes(edits, deleted_lines_a), begin, ctx, lnums_b, texts_b, filename_b)
endif

if line[0] ==# ' '
Expand Down Expand Up @@ -135,9 +140,12 @@ fu! s:DiffsIterator.next_modified() abort
let ctx = self.contexts[self.state[self.wlnum]]
silent! unlet self.deleted_ctxs_a[ctx.id]

if !empty(self.lines[self.wlnum - 1]) || filename_b !=# fnameescape(ctx.filename)
if !empty(self.lines[self.wlnum - 1])
throw s:err(s:unexpected_filename_fmt, self.wlnum)
endif
if s:String.ends_with(filename_b, s:path_separator)
throw s:err(s:unexpected_slash_fmt, self.wlnum)
endif

let lines_a = ctx.lines
let deleted_lines_a = copy(lines_a)
Expand All @@ -147,7 +155,7 @@ fu! s:DiffsIterator.next_modified() abort
let self.wlnum += 1
endwhile

return s:Diff.new(self.add_deletes(edits, deleted_lines_a), begin, ctx, lnums_b, texts_b)
return s:Diff.new(self.stats, self.add_deletes(edits, deleted_lines_a), begin, ctx, lnums_b, texts_b, filename_b)
endfu

fu! s:DiffsIterator.add_deletes(edits, deleted_lines_a) abort dict
Expand All @@ -164,19 +172,32 @@ endfu

let s:Diff = {}

fu! s:Diff.new(edits, begin, ctx, lnums_b, texts_b) abort
if empty(a:edits) | return {'edits': []} | endif
let edits = s:reverse_flatten(a:edits)
let win_undos = s:win_undos(a:ctx.lines, a:ctx, a:ctx.begin, a:lnums_b)
let [win_edits, lines_b] = s:win_write_post_edits(edits, a:lnums_b, a:texts_b, a:begin)
return {
fu! s:Diff.new(stats, edits, begin, ctx, lnums_b, texts_b, ...) abort dict
let diff = {}

if a:0 && simplify(fnameescape(a:ctx.filename)) !=# simplify(a:1)
let diff.filename = esearch#shell#fnameunescape(a:1)
let a:stats.renamed += 1
endif

if empty(a:edits)
if empty(diff) | return diff | endif

let [edits, win_undos, win_edits, lines_b] = [[], [], [], a:ctx.lines]
else
let edits = s:reverse_flatten(a:edits)
let win_undos = s:win_undos(a:ctx.lines, a:ctx, a:ctx.begin, a:lnums_b)
let [win_edits, lines_b] = s:win_write_post_edits(edits, a:lnums_b, a:texts_b, a:begin)
endif

return extend(diff, {
\ 'ctx': a:ctx,
\ 'begin': a:begin,
\ 'edits': edits,
\ 'win_edits': win_edits,
\ 'win_undos': win_undos,
\ 'begin': a:begin,
\ 'lines_b': lines_b,
\}
\})
endfu

fu! s:win_write_post_edits(edits, lnums_b, texts_b, begin) abort
Expand Down
23 changes: 15 additions & 8 deletions autoload/esearch/out/win/modifiable.vim
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,23 @@ fu! s:write_cmd() abort
return s:Log.error(substitute(v:exception, '^DiffError:', '', ''))
endtry

if diff.stats.files == 0 | echo 'Nothing to save' | return | endi

let [kinds, total_changes] = [[], diff.stats.modified + diff.stats.deleted + diff.stats.added]
if diff.stats.added > 0 | let kinds += [diff.stats.added . ' added'] | endif
if diff.stats.modified > 0 | let kinds += [diff.stats.modified . ' modified'] | endif
if diff.stats.deleted > 0 | let kinds += [diff.stats.deleted . ' deleted'] | endif
if diff.stats.files == 0 | echo 'Nothing to save' | return | endif

let stats = diff.stats
let [kinds, total_changes] = [[], stats.modified + stats.deleted + stats.added]
if stats.added > 0 | let kinds += [stats.added . ' added'] | endif
if stats.modified > 0 | let kinds += [stats.modified . ' modified'] | endif
if stats.deleted > 0 | let kinds += [stats.deleted . ' deleted'] | endif
if stats.renamed > 0
let renamed = ', ' . stats.renamed . ' renamed ' . (stats.renamed == 1 ? 'file' : 'files')
else
let renamed = ''
endif

let message = printf('Write changes? (%s %s in %d %s)',
let message = printf('Write changes? (%s %s in %d %s%s)',
\ join(kinds, ', '), total_changes == 1 ? 'line' : 'lines',
\ diff.stats.files, diff.stats.files == 1 ? 'file' : 'files')
\ stats.files, stats.files == 1 ? 'file' : 'files',
\ renamed)
if !get(g:, 'esearch_yes') && confirm(message, "&Yes\n&Cancel") != 1 | return |endif

call esearch#writer#do(diff, b:esearch, v:cmdbang)
Expand Down
1 change: 1 addition & 0 deletions autoload/esearch/out/win/update.vim
Original file line number Diff line number Diff line change
Expand Up @@ -189,4 +189,5 @@ fu! esearch#out#win#update#finish(bufnr) abort
cal setbufvar(a:bufnr, '&modified', 0)
cal esearch#out#win#modifiable#init()
if es.win_ui_nvim_syntax | cal luaeval('esearch.buf_attach_ui()') | en
let es.linecount = line('$')
endfu
5 changes: 5 additions & 0 deletions autoload/esearch/shell.vim
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,12 @@ elseif g:esearch#has#vms
else
let s:path_esc_chars = " \t\n*?[{`$\\%#'\"|!<"
endif
let s:path_unesc_re = '\\\(' . join(map(split(s:path_esc_chars, '\zs'), 'escape(v:val, ''^$~.*[]\'')'), '\|') . '\)'

fu! s:fnameescape(string) abort
return escape(a:string, s:metachars . s:path_esc_chars)
endfu

fu! esearch#shell#fnameunescape(fname) abort
return substitute(a:fname, s:path_unesc_re, '\1', 'g')
endfu
16 changes: 16 additions & 0 deletions autoload/esearch/util.vim
Original file line number Diff line number Diff line change
Expand Up @@ -304,3 +304,19 @@ endfu
fu! esearch#util#noop(...) abort
return 0
endfu

fu! esearch#util#file_exists(path) abort
let [dirname, basename] = [s:Filepath.dirname(a:path), s:Filepath.basename(a:path)]
return !empty(globpath(dirname, basename, 1))
endfu

fu! esearch#util#list2dict(list) abort
let [i, dict] = [0, {}]

while i < len(a:list)
let dict[i + 1] = a:list[i]
let i += 1
endwhile

return dict
endfu
Loading