my dotfiles
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

539 lines
19 KiB

  1. " cecutil.vim : save/restore window position
  2. " save/restore mark position
  3. " save/restore selected user maps
  4. " Author: Charles E. Campbell
  5. " Version: 18i ASTRO-ONLY
  6. " Date: Oct 21, 2013
  7. "
  8. " Saving Restoring Destroying Marks: {{{1
  9. " call SaveMark(markname) let savemark= SaveMark(markname)
  10. " call RestoreMark(markname) call RestoreMark(savemark)
  11. " call DestroyMark(markname)
  12. " commands: SM RM DM
  13. "
  14. " Saving Restoring Destroying Window Position: {{{1
  15. " call SaveWinPosn() let winposn= SaveWinPosn()
  16. " call RestoreWinPosn() call RestoreWinPosn(winposn)
  17. " \swp : save current window/buffer's position
  18. " \rwp : restore current window/buffer's previous position
  19. " commands: SWP RWP
  20. "
  21. " Saving And Restoring User Maps: {{{1
  22. " call SaveUserMaps(mapmode,maplead,mapchx,suffix)
  23. " call RestoreUserMaps(suffix)
  24. "
  25. " GetLatestVimScripts: 1066 1 :AutoInstall: cecutil.vim
  26. "
  27. " You believe that God is one. You do well. The demons also {{{1
  28. " believe, and shudder. But do you want to know, vain man, that
  29. " faith apart from works is dead? (James 2:19,20 WEB)
  30. "redraw!|call inputsave()|call input("Press <cr> to continue")|call inputrestore()
  31. " ---------------------------------------------------------------------
  32. " Load Once: {{{1
  33. if &cp || exists("g:loaded_cecutil")
  34. finish
  35. endif
  36. let g:loaded_cecutil = "v18i"
  37. let s:keepcpo = &cpo
  38. set cpo&vim
  39. "DechoRemOn
  40. " =======================
  41. " Public Interface: {{{1
  42. " =======================
  43. " ---------------------------------------------------------------------
  44. " Map Interface: {{{2
  45. if !exists('g:no_plugin_maps') && !exists('g:no_cecutil_maps')
  46. if !hasmapto('<Plug>SaveWinPosn')
  47. map <unique> <Leader>swp <Plug>SaveWinPosn
  48. endif
  49. if !hasmapto('<Plug>RestoreWinPosn')
  50. map <unique> <Leader>rwp <Plug>RestoreWinPosn
  51. endif
  52. endif
  53. nmap <silent> <Plug>SaveWinPosn :call SaveWinPosn()<CR>
  54. nmap <silent> <Plug>RestoreWinPosn :call RestoreWinPosn()<CR>
  55. " ---------------------------------------------------------------------
  56. " Command Interface: {{{2
  57. com! -bar -nargs=0 SWP call SaveWinPosn()
  58. com! -bar -nargs=? RWP call RestoreWinPosn(<args>)
  59. com! -bar -nargs=1 SM call SaveMark(<q-args>)
  60. com! -bar -nargs=1 RM call RestoreMark(<q-args>)
  61. com! -bar -nargs=1 DM call DestroyMark(<q-args>)
  62. com! -bar -nargs=1 WLR call s:WinLineRestore(<q-args>)
  63. if v:version < 630
  64. let s:modifier= "sil! "
  65. else
  66. let s:modifier= "sil! keepj "
  67. endif
  68. " ===============
  69. " Functions: {{{1
  70. " ===============
  71. " ---------------------------------------------------------------------
  72. " SaveWinPosn: {{{2
  73. " let winposn= SaveWinPosn() will save window position in winposn variable
  74. " call SaveWinPosn() will save window position in b:cecutil_winposn{b:cecutil_iwinposn}
  75. " let winposn= SaveWinPosn(0) will *only* save window position in winposn variable (no stacking done)
  76. fun! SaveWinPosn(...)
  77. " echomsg "Decho: SaveWinPosn() a:0=".a:0
  78. if line("$") == 1 && getline(1) == ""
  79. " echomsg "Decho: SaveWinPosn : empty buffer"
  80. return ""
  81. endif
  82. let so_keep = &l:so
  83. let siso_keep = &siso
  84. let ss_keep = &l:ss
  85. setlocal so=0 siso=0 ss=0
  86. let swline = line(".") " save-window line in file
  87. let swcol = col(".") " save-window column in file
  88. if swcol >= col("$")
  89. let swcol= swcol + virtcol(".") - virtcol("$") " adjust for virtual edit (cursor past end-of-line)
  90. endif
  91. let swwline = winline() - 1 " save-window window line
  92. let swwcol = virtcol(".") - wincol() " save-window window column
  93. let savedposn = ""
  94. " echomsg "Decho: sw[".swline.",".swcol."] sww[".swwline.",".swwcol."]"
  95. let savedposn = "call GoWinbufnr(".winbufnr(0).")"
  96. let savedposn = savedposn."|".s:modifier.swline
  97. let savedposn = savedposn."|".s:modifier."norm! 0z\<cr>"
  98. if swwline > 0
  99. let savedposn= savedposn.":".s:modifier."call s:WinLineRestore(".(swwline+1).")\<cr>"
  100. endif
  101. if swwcol > 0
  102. let savedposn= savedposn.":".s:modifier."norm! 0".swwcol."zl\<cr>"
  103. endif
  104. let savedposn = savedposn.":".s:modifier."call cursor(".swline.",".swcol.")\<cr>"
  105. " save window position in
  106. " b:cecutil_winposn_{iwinposn} (stack)
  107. " only when SaveWinPosn() is used
  108. if a:0 == 0
  109. if !exists("b:cecutil_iwinposn")
  110. let b:cecutil_iwinposn= 1
  111. else
  112. let b:cecutil_iwinposn= b:cecutil_iwinposn + 1
  113. endif
  114. " echomsg "Decho: saving posn to SWP stack"
  115. let b:cecutil_winposn{b:cecutil_iwinposn}= savedposn
  116. endif
  117. let &l:so = so_keep
  118. let &siso = siso_keep
  119. let &l:ss = ss_keep
  120. " if exists("b:cecutil_iwinposn") " Decho
  121. " echomsg "Decho: b:cecutil_winpos{".b:cecutil_iwinposn."}[".b:cecutil_winposn{b:cecutil_iwinposn}."]"
  122. " else " Decho
  123. " echomsg "Decho: b:cecutil_iwinposn doesn't exist"
  124. " endif " Decho
  125. " echomsg "Decho: SaveWinPosn [".savedposn."]"
  126. return savedposn
  127. endfun
  128. " ---------------------------------------------------------------------
  129. " RestoreWinPosn: {{{2
  130. " call RestoreWinPosn()
  131. " call RestoreWinPosn(winposn)
  132. fun! RestoreWinPosn(...)
  133. " echomsg "Decho: RestoreWinPosn() a:0=".a:0
  134. " echomsg "Decho: getline(1)<".getline(1).">"
  135. " echomsg "Decho: line(.)=".line(".")
  136. if line("$") == 1 && getline(1) == ""
  137. " echomsg "Decho: RestoreWinPosn : empty buffer"
  138. return ""
  139. endif
  140. let so_keep = &l:so
  141. let siso_keep = &l:siso
  142. let ss_keep = &l:ss
  143. setlocal so=0 siso=0 ss=0
  144. if a:0 == 0 || a:1 == ""
  145. " use saved window position in b:cecutil_winposn{b:cecutil_iwinposn} if it exists
  146. if exists("b:cecutil_iwinposn") && exists("b:cecutil_winposn{b:cecutil_iwinposn}")
  147. " echomsg "Decho: using stack b:cecutil_winposn{".b:cecutil_iwinposn."}<".b:cecutil_winposn{b:cecutil_iwinposn}.">"
  148. try
  149. exe s:modifier.b:cecutil_winposn{b:cecutil_iwinposn}
  150. catch /^Vim\%((\a\+)\)\=:E749/
  151. " ignore empty buffer error messages
  152. endtry
  153. " normally drop top-of-stack by one
  154. " but while new top-of-stack doesn't exist
  155. " drop top-of-stack index by one again
  156. if b:cecutil_iwinposn >= 1
  157. unlet b:cecutil_winposn{b:cecutil_iwinposn}
  158. let b:cecutil_iwinposn= b:cecutil_iwinposn - 1
  159. while b:cecutil_iwinposn >= 1 && !exists("b:cecutil_winposn{b:cecutil_iwinposn}")
  160. let b:cecutil_iwinposn= b:cecutil_iwinposn - 1
  161. endwhile
  162. if b:cecutil_iwinposn < 1
  163. unlet b:cecutil_iwinposn
  164. endif
  165. endif
  166. else
  167. echohl WarningMsg
  168. echomsg "***warning*** need to SaveWinPosn first!"
  169. echohl None
  170. endif
  171. else " handle input argument
  172. " echomsg "Decho: using input a:1<".a:1.">"
  173. " use window position passed to this function
  174. exe a:1
  175. " remove a:1 pattern from b:cecutil_winposn{b:cecutil_iwinposn} stack
  176. if exists("b:cecutil_iwinposn")
  177. let jwinposn= b:cecutil_iwinposn
  178. while jwinposn >= 1 " search for a:1 in iwinposn..1
  179. if exists("b:cecutil_winposn{jwinposn}") " if it exists
  180. if a:1 == b:cecutil_winposn{jwinposn} " and the pattern matches
  181. unlet b:cecutil_winposn{jwinposn} " unlet it
  182. if jwinposn == b:cecutil_iwinposn " if at top-of-stack
  183. let b:cecutil_iwinposn= b:cecutil_iwinposn - 1 " drop stacktop by one
  184. endif
  185. endif
  186. endif
  187. let jwinposn= jwinposn - 1
  188. endwhile
  189. endif
  190. endif
  191. " Seems to be something odd: vertical motions after RWP
  192. " cause jump to first column. The following fixes that.
  193. " Note: was using wincol()>1, but with signs, a cursor
  194. " at column 1 yields wincol()==3. Beeping ensued.
  195. let vekeep= &ve
  196. set ve=all
  197. if virtcol('.') > 1
  198. exe s:modifier."norm! hl"
  199. elseif virtcol(".") < virtcol("$")
  200. exe s:modifier."norm! lh"
  201. endif
  202. let &ve= vekeep
  203. let &l:so = so_keep
  204. let &l:siso = siso_keep
  205. let &l:ss = ss_keep
  206. " echomsg "Decho: RestoreWinPosn"
  207. endfun
  208. " ---------------------------------------------------------------------
  209. " s:WinLineRestore: {{{2
  210. fun! s:WinLineRestore(swwline)
  211. " echomsg "Decho: s:WinLineRestore(swwline=".a:swwline.")"
  212. while winline() < a:swwline
  213. let curwinline= winline()
  214. exe s:modifier."norm! \<c-y>"
  215. if curwinline == winline()
  216. break
  217. endif
  218. endwhile
  219. " echomsg "Decho: s:WinLineRestore"
  220. endfun
  221. " ---------------------------------------------------------------------
  222. " GoWinbufnr: go to window holding given buffer (by number) {{{2
  223. " Prefers current window; if its buffer number doesn't match,
  224. " then will try from topleft to bottom right
  225. fun! GoWinbufnr(bufnum)
  226. " call Dfunc("GoWinbufnr(".a:bufnum.")")
  227. if winbufnr(0) == a:bufnum
  228. " call Dret("GoWinbufnr : winbufnr(0)==a:bufnum")
  229. return
  230. endif
  231. winc t
  232. let first=1
  233. while winbufnr(0) != a:bufnum && (first || winnr() != 1)
  234. winc w
  235. let first= 0
  236. endwhile
  237. " call Dret("GoWinbufnr")
  238. endfun
  239. " ---------------------------------------------------------------------
  240. " SaveMark: sets up a string saving a mark position. {{{2
  241. " For example, SaveMark("a")
  242. " Also sets up a global variable, g:savemark_{markname}
  243. fun! SaveMark(markname)
  244. " call Dfunc("SaveMark(markname<".a:markname.">)")
  245. let markname= a:markname
  246. if strpart(markname,0,1) !~ '\a'
  247. let markname= strpart(markname,1,1)
  248. endif
  249. " call Decho("markname=".markname)
  250. let lzkeep = &lz
  251. set lz
  252. if 1 <= line("'".markname) && line("'".markname) <= line("$")
  253. let winposn = SaveWinPosn(0)
  254. exe s:modifier."norm! `".markname
  255. let savemark = SaveWinPosn(0)
  256. let g:savemark_{markname} = savemark
  257. let savemark = markname.savemark
  258. call RestoreWinPosn(winposn)
  259. else
  260. let g:savemark_{markname} = ""
  261. let savemark = ""
  262. endif
  263. let &lz= lzkeep
  264. " call Dret("SaveMark : savemark<".savemark.">")
  265. return savemark
  266. endfun
  267. " ---------------------------------------------------------------------
  268. " RestoreMark: {{{2
  269. " call RestoreMark("a") -or- call RestoreMark(savemark)
  270. fun! RestoreMark(markname)
  271. " call Dfunc("RestoreMark(markname<".a:markname.">)")
  272. if strlen(a:markname) <= 0
  273. " call Dret("RestoreMark : no such mark")
  274. return
  275. endif
  276. let markname= strpart(a:markname,0,1)
  277. if markname !~ '\a'
  278. " handles 'a -> a styles
  279. let markname= strpart(a:markname,1,1)
  280. endif
  281. " call Decho("markname=".markname." strlen(a:markname)=".strlen(a:markname))
  282. let lzkeep = &lz
  283. set lz
  284. let winposn = SaveWinPosn(0)
  285. if strlen(a:markname) <= 2
  286. if exists("g:savemark_{markname}") && strlen(g:savemark_{markname}) != 0
  287. " use global variable g:savemark_{markname}
  288. " call Decho("use savemark list")
  289. call RestoreWinPosn(g:savemark_{markname})
  290. exe "norm! m".markname
  291. endif
  292. else
  293. " markname is a savemark command (string)
  294. " call Decho("use savemark command")
  295. let markcmd= strpart(a:markname,1)
  296. call RestoreWinPosn(markcmd)
  297. exe "norm! m".markname
  298. endif
  299. call RestoreWinPosn(winposn)
  300. let &lz = lzkeep
  301. " call Dret("RestoreMark")
  302. endfun
  303. " ---------------------------------------------------------------------
  304. " DestroyMark: {{{2
  305. " call DestroyMark("a") -- destroys mark
  306. fun! DestroyMark(markname)
  307. " call Dfunc("DestroyMark(markname<".a:markname.">)")
  308. " save options and set to standard values
  309. let reportkeep= &report
  310. let lzkeep = &lz
  311. set lz report=10000
  312. let markname= strpart(a:markname,0,1)
  313. if markname !~ '\a'
  314. " handles 'a -> a styles
  315. let markname= strpart(a:markname,1,1)
  316. endif
  317. " call Decho("markname=".markname)
  318. let curmod = &mod
  319. let winposn = SaveWinPosn(0)
  320. 1
  321. let lineone = getline(".")
  322. exe "k".markname
  323. d
  324. put! =lineone
  325. let &mod = curmod
  326. call RestoreWinPosn(winposn)
  327. " restore options to user settings
  328. let &report = reportkeep
  329. let &lz = lzkeep
  330. " call Dret("DestroyMark")
  331. endfun
  332. " ---------------------------------------------------------------------
  333. " QArgSplitter: to avoid \ processing by <f-args>, <q-args> is needed. {{{2
  334. " However, <q-args> doesn't split at all, so this one returns a list
  335. " with splits at all whitespace (only!), plus a leading length-of-list.
  336. " The resulting list: qarglist[0] corresponds to a:0
  337. " qarglist[i] corresponds to a:{i}
  338. fun! QArgSplitter(qarg)
  339. " call Dfunc("QArgSplitter(qarg<".a:qarg.">)")
  340. let qarglist = split(a:qarg)
  341. let qarglistlen = len(qarglist)
  342. let qarglist = insert(qarglist,qarglistlen)
  343. " call Dret("QArgSplitter ".string(qarglist))
  344. return qarglist
  345. endfun
  346. " ---------------------------------------------------------------------
  347. " ListWinPosn: {{{2
  348. "fun! ListWinPosn() " Decho
  349. " if !exists("b:cecutil_iwinposn") || b:cecutil_iwinposn == 0 " Decho
  350. " call Decho("nothing on SWP stack") " Decho
  351. " else " Decho
  352. " let jwinposn= b:cecutil_iwinposn " Decho
  353. " while jwinposn >= 1 " Decho
  354. " if exists("b:cecutil_winposn{jwinposn}") " Decho
  355. " call Decho("winposn{".jwinposn."}<".b:cecutil_winposn{jwinposn}.">") " Decho
  356. " else " Decho
  357. " call Decho("winposn{".jwinposn."} -- doesn't exist") " Decho
  358. " endif " Decho
  359. " let jwinposn= jwinposn - 1 " Decho
  360. " endwhile " Decho
  361. " endif " Decho
  362. "endfun " Decho
  363. "com! -nargs=0 LWP call ListWinPosn() " Decho
  364. " ---------------------------------------------------------------------
  365. " SaveUserMaps: this function sets up a script-variable (s:restoremap) {{{2
  366. " which can be used to restore user maps later with
  367. " call RestoreUserMaps()
  368. "
  369. " mapmode - see :help maparg for details (n v o i c l "")
  370. " ex. "n" = Normal
  371. " The letters "b" and "u" are optional prefixes;
  372. " The "u" means that the map will also be unmapped
  373. " The "b" means that the map has a <buffer> qualifier
  374. " ex. "un" = Normal + unmapping
  375. " ex. "bn" = Normal + <buffer>
  376. " ex. "bun" = Normal + <buffer> + unmapping
  377. " ex. "ubn" = Normal + <buffer> + unmapping
  378. " maplead - see mapchx
  379. " mapchx - "<something>" handled as a single map item.
  380. " ex. "<left>"
  381. " - "string" a string of single letters which are actually
  382. " multiple two-letter maps (using the maplead:
  383. " maplead . each_character_in_string)
  384. " ex. maplead="\" and mapchx="abc" saves user mappings for
  385. " \a, \b, and \c
  386. " Of course, if maplead is "", then for mapchx="abc",
  387. " mappings for a, b, and c are saved.
  388. " - :something handled as a single map item, w/o the ":"
  389. " ex. mapchx= ":abc" will save a mapping for "abc"
  390. " suffix - a string unique to your plugin
  391. " ex. suffix= "DrawIt"
  392. fun! SaveUserMaps(mapmode,maplead,mapchx,suffix)
  393. " call Dfunc("SaveUserMaps(mapmode<".a:mapmode."> maplead<".a:maplead."> mapchx<".a:mapchx."> suffix<".a:suffix.">)")
  394. if !exists("s:restoremap_{a:suffix}")
  395. " initialize restoremap_suffix to null string
  396. let s:restoremap_{a:suffix}= ""
  397. endif
  398. " set up dounmap: if 1, then save and unmap (a:mapmode leads with a "u")
  399. " if 0, save only
  400. let mapmode = a:mapmode
  401. let dounmap = 0
  402. let dobuffer = ""
  403. while mapmode =~ '^[bu]'
  404. if mapmode =~ '^u'
  405. let dounmap = 1
  406. let mapmode = strpart(a:mapmode,1)
  407. elseif mapmode =~ '^b'
  408. let dobuffer = "<buffer> "
  409. let mapmode = strpart(a:mapmode,1)
  410. endif
  411. endwhile
  412. " call Decho("dounmap=".dounmap." dobuffer<".dobuffer.">")
  413. " save single map :...something...
  414. if strpart(a:mapchx,0,1) == ':'
  415. " call Decho("save single map :...something...")
  416. let amap= strpart(a:mapchx,1)
  417. if amap == "|" || amap == "\<c-v>"
  418. let amap= "\<c-v>".amap
  419. endif
  420. let amap = a:maplead.amap
  421. let s:restoremap_{a:suffix} = s:restoremap_{a:suffix}."|:sil! ".mapmode."unmap ".dobuffer.amap
  422. if maparg(amap,mapmode) != ""
  423. let maprhs = substitute(maparg(amap,mapmode),'|','<bar>','ge')
  424. let s:restoremap_{a:suffix} = s:restoremap_{a:suffix}."|:".mapmode."map ".dobuffer.amap." ".maprhs
  425. endif
  426. if dounmap
  427. exe "sil! ".mapmode."unmap ".dobuffer.amap
  428. endif
  429. " save single map <something>
  430. elseif strpart(a:mapchx,0,1) == '<'
  431. " call Decho("save single map <something>")
  432. let amap = a:mapchx
  433. if amap == "|" || amap == "\<c-v>"
  434. let amap= "\<c-v>".amap
  435. " call Decho("amap[[".amap."]]")
  436. endif
  437. let s:restoremap_{a:suffix} = s:restoremap_{a:suffix}."|sil! ".mapmode."unmap ".dobuffer.amap
  438. if maparg(a:mapchx,mapmode) != ""
  439. let maprhs = substitute(maparg(amap,mapmode),'|','<bar>','ge')
  440. let s:restoremap_{a:suffix} = s:restoremap_{a:suffix}."|".mapmode."map ".dobuffer.amap." ".maprhs
  441. endif
  442. if dounmap
  443. exe "sil! ".mapmode."unmap ".dobuffer.amap
  444. endif
  445. " save multiple maps
  446. else
  447. " call Decho("save multiple maps")
  448. let i= 1
  449. while i <= strlen(a:mapchx)
  450. let amap= a:maplead.strpart(a:mapchx,i-1,1)
  451. if amap == "|" || amap == "\<c-v>"
  452. let amap= "\<c-v>".amap
  453. endif
  454. let s:restoremap_{a:suffix} = s:restoremap_{a:suffix}."|sil! ".mapmode."unmap ".dobuffer.amap
  455. if maparg(amap,mapmode) != ""
  456. let maprhs = substitute(maparg(amap,mapmode),'|','<bar>','ge')
  457. let s:restoremap_{a:suffix} = s:restoremap_{a:suffix}."|".mapmode."map ".dobuffer.amap." ".maprhs
  458. endif
  459. if dounmap
  460. exe "sil! ".mapmode."unmap ".dobuffer.amap
  461. endif
  462. let i= i + 1
  463. endwhile
  464. endif
  465. " call Dret("SaveUserMaps : restoremap_".a:suffix.": ".s:restoremap_{a:suffix})
  466. endfun
  467. " ---------------------------------------------------------------------
  468. " RestoreUserMaps: {{{2
  469. " Used to restore user maps saved by SaveUserMaps()
  470. fun! RestoreUserMaps(suffix)
  471. " call Dfunc("RestoreUserMaps(suffix<".a:suffix.">)")
  472. if exists("s:restoremap_{a:suffix}")
  473. let s:restoremap_{a:suffix}= substitute(s:restoremap_{a:suffix},'|\s*$','','e')
  474. if s:restoremap_{a:suffix} != ""
  475. " call Decho("exe ".s:restoremap_{a:suffix})
  476. exe "sil! ".s:restoremap_{a:suffix}
  477. endif
  478. unlet s:restoremap_{a:suffix}
  479. endif
  480. " call Dret("RestoreUserMaps")
  481. endfun
  482. " ==============
  483. " Restore: {{{1
  484. " ==============
  485. let &cpo= s:keepcpo
  486. unlet s:keepcpo
  487. " ================
  488. " Modelines: {{{1
  489. " ================
  490. " vim: ts=4 fdm=marker