How to permanently delete a specific entry from Vim's command-line history without losing the changelists of the recently edited files? -
when execute vim ex command, gets saved in command-line history, can access opening command-line window q:
.
however, sometimes, want able remove of them permanently. example, if execute command :a
, subsequent commands in command-line window recognized elements of syntax group viminsert
, linked highlight group string
, colored in cyan in colorscheme.
to fix syntax highlighting, try delete :a
command command-line window hitting dd
, entry removed while window opened. close it, , reopen later, :a
command back. make removal permanent, tried add autocmd in vimrc
:
augroup my_cmdline_window au! au cmdwinleave * call s:update_history() augroup end fu! s:update_history() abort let new_hist = getline(1, '$') call histdel(':') in new_hist call histadd(':', i) endfor endfu
it calls function, updates command history reading current window, before closing it. works while current vim session running, quit start new one, deleted entries back.
i think reason why removal doesn't persist across sessions, because when quit session vim merges current command-line history 1 stored in ~/.viminfo
.
what saved inside file controlled 'viminfo'
option. value of 'viminfo'
is:
viminfo='100,<50,s10,h
it doesn't contain :
parameter, sets maximum number of items in command-line history, saved. means vim should use 'history'
option. default value of 'history'
1000
.
so, force vim overwrite command-line history stored inside ~/.viminfo
1 of current session, tried use :wviminfo
command inside autocmd:
augroup my_cmdline_window au! au cmdwinleave * call s:update_history() augroup end fu! s:update_history() abort let new_hist = getline(1, '$') call histdel(':') in new_hist call histadd(':', i) endfor wviminfo! endfu
i added bang :wviminfo
, according :h :wviminfo
:
when [!] used, old information not read first, internal info written.
it seems work, because autocmd, removal of entry inside command-line window persists across sessions. however, seems erase changelists of edited files, because after starting new vim session, changelists empty.
and since :h 'viminfo
explains when include '
item in 'viminfo'
, changelist , jumplist stored in ~/.viminfo
, suspect jumplist , marks lost after using :wviminfo!
.
is there way avoid loss of changelists/jumplists/marks, while still removing arbitrary entry command-line history?
edit:
i came this:
augroup my_cmdline_window au! au cmdwinenter * let s:old_cmdline_hist = getline(1, line('$')-1) au cmdwinleave * call s:update_history() augroup end fu! s:update_history() abort let hist = filter(getline(1, '$'), 'v:val !~# "^\\s*$"') call histdel(':') in hist call histadd(':', i) endfor let viminfo = expand('~/.viminfo') if !filereadable(viminfo) return endif let info = readfile(viminfo) let deleted_entries = filter(copy(s:old_cmdline_hist), 'index(hist, v:val) == -1') call map(deleted_entries, 'index(info, ":".v:val)') call sort(filter(deleted_entries, 'v:val >= 0')) if empty(deleted_entries) return endif entry in reverse(deleted_entries) call remove(info, entry, entry + 1) endfor call writefile(info, viminfo, 'b') endfu
here's code does:
when enter command-line window, 1st autocmd captures command-line history inside s:old_cmdline_hist
.
when leave it, 2nd autocmd updates history of current session, , tries remove deleted entries ~/.viminfo
.
let hist = filter(getline(1, '$'), 'v:val !~# "^\\s*$"') call histdel(':') in hist call histadd(':', i) endfor
this block updates history of current session.
let viminfo = expand('~/.viminfo') if !filereadable(viminfo) return endif
this 1 checks whether ~/.viminfo
readable. if it's not, function stops.
let info = readfile(viminfo) let deleted_entries = filter(copy(s:old_cmdline_hist), 'index(hist, v:val) == -1')
this block gets contents of ~/.viminfo
inside list info
(1 item = 1 line). gets entries deleted invoking filter()
. latter removes entries don't satisfy condition index(hist, v:val) == -1
. expression true if entry of old history, on filter()
operates, not inside new history.
call map(deleted_entries, 'index(info, ":".v:val)')
this line converts deleted text entries line addresses inside ~/.viminfo
.
call sort(filter(deleted_entries, 'v:val >= 0')) if empty(deleted_entries) return endif
this block sorts line addresses, , removes ones not positive, in case of them weren't found in previous step (index()
returned -1
). checks whether there still line addresses @ point, , if there aren't, again, function stops.
for entry in reverse(deleted_entries) call remove(info, entry, entry + 1) endfor
this block removes relevant lines info
. deletes 2 lines (entry
, entry + 1
), because every command-line saved in ~/.viminfo
, there's 2nd line seems timestamp. also, deletes in reverse order, not have update addresses of lines delete (every time delete line, addresses of next ones decreased one).
call writefile(info, viminfo, 'b')
this line overwrites ~/.viminfo
new contents, should same before, without lines deleted in command-line window.
i don't post answer, i'm not sure it's reliable , there aren't side-effects. did backup of ~/.viminfo
before testing code.
edit2:
i don't think it's able delete line contains literal carriage return. there may other special characters causing similar issue (like null character ^@
).
Comments
Post a Comment