├── README.md └── nav.vim /README.md: -------------------------------------------------------------------------------- 1 | #microViche 2 | MicroViche is sort of like a [microfiche](http://www.wisegeek.org/what-is-microfiche.htm) reader: it lets you pan and zoom through text. Installation is simple: [download](https://raw.github.com/q335r49/textabyss/master/nav.vim) nav.vim, open [Vim](http://www.vim.org), :source nav.vim, and press f10. Check out the **[youtube video](https://www.youtube.com/watch?v=9YNiPUTGO28)**! 3 | 4 | ####Commands 5 | Use the mouse to pan or evoke commands with f10: 6 | 7 | h j k l y u b n | pan (takes count) || f1 | help and warnings 8 | :---: | :---: | :---: | :---: | :---: 9 | r M | redraw visible / all || o | open map 10 | A D | append / delete split || L | insert label 11 | S W | settings / save settings || q esc | quit 12 | 13 | In the map (f10 o): 14 | 15 | h j k l y u b n | move (takes count) || f1 | help and warnings 16 | :---: | :---: | :---: | :---: | :---: 17 | H J K L Y U B N | pan (takes count) || z | zoom 18 | g enter doubleclick | goto label || c C | center cursor / view 19 | click drag | select / pan || q esc | quit 20 | p P | prev / next in history || 21 | 22 | ####Labels 23 | Labels are lines that start with a label marker (default txb:) and specify an anchor, title, or both. When the map is updated (f10 r, o, and M), displaced labels are reanchored by inserting or removing immediately preceding blank lines. Anchoring failures are shown in the map. 24 | 25 | The syntax is marker(anchor)(:)( title#highlght#comment), but let's just consider some examples: 26 |    txb:345 blah blah        anchor to line 345 27 |    txb:345: Intro#Search    anchor 345, title Intro, color Search (Note the : separator). 28 |    txb: Intro               just title Intro 29 |    txb: Intro## blah blah   just title Intro 30 | 31 | ####Tips 32 | - To resolve **labeling conflicts**, the case-insensitive alphabetically first title starting with ! will be shown, eg, txb:321: !aaaImportant. On cursor-over, the rest will be shown in line number order. 33 | - **Terminal emulators** work better than gVim since the latter doesn't support mousing in map mode or automatic redrawing on window / font resize. [Cygwin](http://www.cygwin.com/) (and the bundled [mintty](https://code.google.com/p/mintty/) terminal emulator) is a great Windows setup. 34 | - To **disable scrollbinding**: f10 Settings→ change autoexe to se **no**scb nowrap→apply all 35 | - **Keyboard-free navigation** is possible: dragging to the topleft corner opens the map and clicking the topleft corner closes it. (Terminal emulator only; ttymouse must be set to sgr or xterm2.) 36 | - If you have an **inaccessible hotkey**, :call TxbKey('S') for Settings. 37 | - To **highight labels**, try: syntax match Title +^txb\S*: \zs.[^#\n]*+ oneline display 38 | -------------------------------------------------------------------------------- /nav.vim: -------------------------------------------------------------------------------- 1 | "github.com/q335r49/microviche 2 | 3 | if &cp|se nocompatible|en "(Vital) Enable vim features 4 | se noequalalways winwidth=1 winminwidth=0 "(Vital) Needed for correct panning 5 | se sidescroll=1 "Smoother panning 6 | se nostartofline "Keeps cursor in the same position when panning 7 | se mouse=a "Enables mouse 8 | se lazyredraw "Less redraws 9 | se virtualedit=all "Makes leftmost split align correctly 10 | se hidden "Suppresses error messages when a modified buffer pans offscreen 11 | se scrolloff=0 "Ensures correct vertical panning 12 | 13 | augroup TXB | au! 14 | 15 | let TXB_HOTKEY=exists('TXB_HOTKEY')? TXB_HOTKEY : '' 16 | let s:hotkeyArg=':if exists("w:txbi")\|call TxbKey("null")\|else\|if !TxbInit(exists("TXB")? TXB : "")\|let TXB=t:txb\|en\|en' 17 | exe 'nn ' TXB_HOTKEY s:hotkeyArg 18 | au VimEnter * if escape(maparg(''),'|')==?s:hotkeyArg | exe 'silent! nunmap ' | en | exe 'nn ' TXB_HOTKEY s:hotkeyArg 19 | 20 | if has('gui_running') 21 | nn :exe txbMouse.default() 22 | else 23 | au VimResized * if exists('w:txbi') | call s:redraw() |sil call s:nav(eval(join(map(range(1,winnr()-1),'winwidth(v:val)'),'+').'+winnr()-1+wincol()')/2-&co/4,line('w0')-winheight(0)/4+winline()/2) | en 24 | nn :exe txbMouse[has_key(txbMouse,&ttymouse)? &ttymouse : 'default']() 25 | en 26 | 27 | fun! TxbInit(seed) 28 | se noequalalways winwidth=1 winminwidth=0 29 | if empty(a:seed) 30 | let wdir=input("# Creating a new plane...\n? Working dir: ",getcwd(),'file') 31 | while !isdirectory(wdir) 32 | if empty(wdir) 33 | return 1 34 | en 35 | let wdir=input("\n# (Invalid directory)\n? Working dir: ",getcwd(),'file') 36 | endwhile 37 | let plane={'settings':{'working dir':fnamemodify(wdir,':p')}} 38 | exe 'cd' fnameescape(plane.settings['working dir']) 39 | let input=input("\n? Starting files (single file or filepattern, eg, '*.txt'): ",'','file') 40 | let plane.name=split(glob(input),"\n") 41 | silent cd - 42 | if empty(input) 43 | return 1 44 | en 45 | else 46 | let plane=type(a:seed)==4? deepcopy(a:seed) : type(a:seed)==3? {'name':copy(a:seed)} : {'name':split(glob(a:seed),"\n")} 47 | call filter(plane,'index(["depth","exe","map","name","settings","size"],v:key)!=-1') 48 | en 49 | let prompt='' 50 | for i in keys(plane.settings) 51 | if !exists("s:option[i]['save']") 52 | unlet plane.settings[i] 53 | continue 54 | en 55 | unlet! arg | let arg=plane.settings[i] 56 | exe get(s:option[i],'check','let msg=0') 57 | if msg is 0 58 | continue 59 | en 60 | unlet! arg | exe get(s:option[i],'getDef','let arg=""') 61 | let plane.settings[i]=arg 62 | let prompt.="\n# Invalid setting (reverting to default): ".i.": ".msg 63 | endfor 64 | for i in filter(keys(s:option),'get(s:option[v:val],"save") && !has_key(plane.settings,v:val)') 65 | unlet! arg | exe get(s:option[i],'getDef','let arg=""') 66 | let plane.settings[i]=arg 67 | endfor 68 | let plane.settings['working dir']=fnamemodify(plane.settings['working dir'],':p') 69 | let plane_save=deepcopy(plane) 70 | let plane.size=has_key(plane,'size')? extend(plane.size,repeat([plane.settings['split width']],len(plane.name)-len(plane.size))) : repeat([60],len(plane.name)) 71 | let plane.map=has_key(plane,'map') && empty(filter(range(len(plane.map)),'type(plane.map[v:val])!=4'))? extend(plane.map,eval('['.join(repeat(['{}'],len(plane.name)-len(plane.map)),',').']')) : eval('['.join(repeat(['{}'],len(plane.name)),',').']') 72 | let plane.exe=has_key(plane,'exe')? extend(plane.exe,repeat([plane.settings.autoexe],len(plane.name)-len(plane.exe))) : repeat([plane.settings.autoexe],len(plane.name)) 73 | let plane.depth=has_key(plane,'depth')? extend(plane.depth,repeat([0],len(plane.name)-len(plane.depth))) : repeat([0],len(plane.name)) 74 | exe 'cd' fnameescape(plane.settings['working dir']) 75 | let unreadable=[] 76 | for i in range(len(plane.name)-1,0,-1) 77 | if !filereadable(plane.name[i]) 78 | if !isdirectory(plane.name[i]) 79 | call add(unreadable,remove(plane.name,i)) 80 | else 81 | call remove(plane.name,i) 82 | en 83 | call remove(plane.size,i) 84 | call remove(plane.exe,i) 85 | call remove(plane.map,i) 86 | en 87 | endfor 88 | let initCmd=index(map(copy(plane.name),'bufnr(fnamemodify(v:val,":p"))'),bufnr(''))==-1? 'tabe' : '' 89 | cd - 90 | ec "\n#" len(plane.name) "readable:" join(plane.name,', ') "\n#" len(unreadable) "unreadable:" join(unreadable,', ') "\n# Working dir:" plane.settings['working dir'] prompt 91 | if empty(plane.name) 92 | ec "# No matches\n? (N)ew plane (S)et working dir & global options (f1) help (esc) cancel: " 93 | let confirmKeys=[-1] 94 | elseif !empty(unreadable) 95 | ec "# Unreadable files will be removed!\n? (R)emove unreadable files and ".(empty(initCmd)? "restore " : "load in new tab ")."(N)ew plane (S)et working dir & global options (f1) help (esc) cancel: " 96 | let confirmKeys=[82,114] 97 | else 98 | ec "? (enter) ".(empty(initCmd)? "restore " : "load in new tab ")."(N)ew plane (S)et working dir & global options (f1) help (esc) cancel: " 99 | let confirmKeys=[10,13] 100 | en 101 | let c=getchar() 102 | echon strtrans(type(c)? c : nr2char(c)) 103 | if index(confirmKeys,c)!=-1 104 | exe initCmd 105 | let t:txb=plane 106 | let t:txbL=len(t:txb.name) 107 | let dict=t:txb.settings 108 | for i in keys(dict) 109 | exe get(s:option[i],'onInit','') 110 | endfor 111 | exe 'cd' fnameescape(plane.settings['working dir']) 112 | let t:bufs=map(copy(plane.name),'bufnr(fnamemodify(v:val,":p"),1)') 113 | cd - 114 | exe empty(a:seed)? g:txbCmd.M : 'redr' 115 | call s:getMapDis() 116 | call s:redraw() 117 | return 0 118 | elseif index([83,115],c)!=-1 119 | let plane=plane_save 120 | call s:settingsPager(plane.settings,['Global','hotkey','mouse pan speed','Plane','working dir'],s:option) 121 | return TxbInit(plane) 122 | elseif index([78,110],c)!=-1 123 | return TxbInit('') 124 | elseif c is "\" 125 | exe g:txbCmd[c] 126 | ec mes 127 | en 128 | return 1 129 | endfun 130 | 131 | let txbMouse={} 132 | fun! txbMouse.default() 133 | if exists('w:txbi') 134 | let cpos=[line('.'),virtcol('.'),w:txbi] 135 | let [c,w0]=[getchar(),-1] 136 | if c!="\" 137 | call s:setCursor(cpos[0],cpos[1],cpos[2]) 138 | echon getwinvar(v:mouse_win,'txbi') '-' v:mouse_lnum 139 | return "keepj norm! \" 140 | en 141 | let ecstr=w:txbi.' '.line('.') 142 | while c!="\" 143 | if v:mouse_win!=w0 144 | let w0=v:mouse_win 145 | exe "norm! \" 146 | if !exists('w:txbi') 147 | return '' 148 | en 149 | let [b0,wrap]=[winbufnr(0),&wrap] 150 | let [x,y,offset]=wrap? [wincol(),line('w0')+winline(),0] : [v:mouse_col-(virtcol('.')-wincol()),v:mouse_lnum,virtcol('.')-wincol()] 151 | else 152 | if wrap 153 | exe "norm! \" 154 | let [nx,l0]=[wincol(),y-winline()] 155 | else 156 | let [nx,l0]=[v:mouse_col-offset,line('w0')+y-v:mouse_lnum] 157 | en 158 | exe 'norm! '.bufwinnr(b0)."\w" 159 | sil let [x,xs]=x && nx? [x,s:nav(x-nx,l0)] : [x? x : nx,0] 160 | let [x,y]=[wrap? v:mouse_win>1? x : nx+xs : x, l0>0? y : y-l0+1] 161 | redr 162 | ec ecstr 163 | en 164 | let c=getchar() 165 | while c!="\" && c!="\" 166 | let c=getchar() 167 | endwhile 168 | endwhile 169 | call s:setCursor(cpos[0],cpos[1],cpos[2]) 170 | echon w:txbi '-' line('.') 171 | return '' 172 | en 173 | let possav=[bufnr('')]+getpos('.')[1:] 174 | call feedkeys("\") 175 | call getchar() 176 | exe v:mouse_win."winc w" 177 | if v:mouse_lnum>line('w$') || &wrap && v:mouse_col%winwidth(0)==1 || !&wrap && v:mouse_col>=winwidth(0)+winsaveview().leftcol || v:mouse_lnum==line('$') 178 | return line('$')==line('w0')? "keepj norm! \\" : "keepj norm! \" 179 | en 180 | exe "norm! \" 181 | redr! 182 | let [veon,fr,tl,v]=[&ve==?'all',-1,repeat([[reltime(),0,0]],4),winsaveview()] 183 | let [v.col,v.coladd,redrexpr]=[0,v:mouse_col-1,(exists('g:opt_device') && g:opt_device==?'droid4' && veon)? 'redr!':'redr'] 184 | let c=getchar() 185 | if c!="\" 186 | return "keepj norm! \" 187 | en 188 | while c=="\" 189 | let [dV,dH,fr]=[min([v:mouse_lnum-v.lnum,v.topline-1]), veon? min([v:mouse_col-v.coladd-1,v.leftcol]):0,(fr+1)%4] 190 | let [v.topline,v.leftcol,v.lnum,v.coladd,tl[fr]]=[v.topline-dV,v.leftcol-dH,v:mouse_lnum-dV,v:mouse_col-1-dH,[reltime(),dV,dH]] 191 | call winrestview(v) 192 | exe redrexpr 193 | let c=getchar() 194 | endwhile 195 | let glide=[99999999]+map(range(11),'11*(11-v:val)*(11-v:val)') 196 | if str2float(reltimestr(reltime(tl[(fr+1)%4][0])))<0.2 197 | let [glv,glh,vc,hc]=[tl[0][1]+tl[1][1]+tl[2][1]+tl[3][1],tl[0][2]+tl[1][2]+tl[2][2]+tl[3][2],0,0] 198 | let [tlx,lnx,glv,lcx,cax,glh]=(glv>3? ['y*v.topline>1','y*v.lnum>1',glv*glv] : glv<-3? ['-(y*v.topline<'.line('$').')','-(y*v.lnum<'.line('$').')',glv*glv] : [0,0,0])+(glh>3? ['x*v.leftcol>0','x*v.coladd>0',glh*glh] : glh<-3? ['-x','-x',glh*glh] : [0,0,0]) 199 | while !getchar(1) && glv+glh 200 | let [y,x,vc,hc]=[vc>get(glide,glv,1),hc>get(glide,glh,1),vc+1,hc+1] 201 | if y||x 202 | let [v.topline,v.lnum,v.leftcol,v.coladd,glv,vc,glh,hc]-=[eval(tlx),eval(lnx),eval(lcx),eval(cax),y,y*vc,x,x*hc] 203 | call winrestview(v) 204 | exe redrexpr 205 | en 206 | endw 207 | en 208 | exe min([max([line('w0'),possav[1]]),line('w$')]) 209 | let firstcol=virtcol('.')-wincol()+1 210 | let lastcol=firstcol+winwidth(0)-1 211 | let possav[3]=min([max([firstcol,possav[2]+possav[3]]),lastcol]) 212 | exe "norm! ".possav[3]."|" 213 | return '' 214 | endfun 215 | 216 | fun! txbMouse.sgr() 217 | if getchar()=="\" 218 | exe "norm! \\" 219 | if exists('w:txbi') 220 | echon w:txbi '-' line('.') 221 | en 222 | elseif !exists('w:txbi') 223 | exe v:mouse_win.'winc w' 224 | if &wrap && (v:mouse_col%winwidth(0)==1 || v:mouse_lnum>line('w$')) || !&wrap && (v:mouse_col>=winwidth(0)+winsaveview().leftcol || v:mouse_lnum>line('w$')) 225 | exe "norm! \" 226 | else 227 | let [s:pX,s:pY]=[0,0] 228 | nno [< :call doDragSGR() 229 | en 230 | else 231 | let [s:pX,s:pY]=[0,0] 232 | nno [< :call doDragSGR() 233 | en 234 | return '' 235 | endfun 236 | fun! txbMouse.xterm2() 237 | if getchar()=="\" 238 | exe "norm! \\" 239 | if exists('w:txbi') 240 | echon w:txbi '-' line('.') 241 | en 242 | elseif !exists('w:txbi') 243 | exe v:mouse_win.'winc w' 244 | if &wrap && (v:mouse_col%winwidth(0)==1 || v:mouse_lnum>line('w$')) || !&wrap && (v:mouse_col>=winwidth(0)+winsaveview().leftcol || v:mouse_lnum>line('w$')) 245 | exe "norm! \" 246 | else 247 | let [s:pX,s:pY]=[0,0] 248 | nno [M :call doDragXterm2() 249 | en 250 | else 251 | let [s:pX,s:pY]=[0,0] 252 | nno [M :call doDragXterm2() 253 | en 254 | return '' 255 | endfun 256 | fun! txbMouse.xterm() 257 | return "norm! \" 258 | endfun 259 | 260 | fun! doDragSGR() 261 | let k=map(split(join(map([getchar(0),getchar(0),getchar(0),getchar(0),getchar(0),getchar(0),getchar(0),getchar(0),getchar(0),getchar(0)],'type(v:val)? v:val : nr2char(v:val)'),''),';'),'str2nr(v:val)') 262 | if len(k)<3 263 | let k=[32,0,0] 264 | elseif k[0]==0 265 | nunmap [< 266 | if !exists('w:txbi') 267 | elseif k[1:]==[1,1] 268 | call TxbKey('o') 269 | else 270 | echon w:txbi '-' line('.') 271 | en 272 | elseif !(k[1] && k[2] && s:pX && s:pY) 273 | elseif exists('w:txbi') 274 | sil call s:nav(s:mps[s:pX-k[1]],line('w0')+s:mps[s:pY-k[2]]) 275 | echon w:txbi '-' line('.') 276 | else 277 | exe 'norm!'.s:panYCmd[s:pY-k[2]].s:panXCmd[s:pX-k[1]] 278 | en 279 | let [s:pX,s:pY]=k[1:2] 280 | while getchar(0) isnot 0 281 | endwhile 282 | endfun 283 | fun! doDragXterm2() 284 | let M=getchar(0) 285 | let X=getchar(0) 286 | let Y=getchar(0) 287 | if M==35 288 | nunmap [M 289 | if !exists('w:txbi') 290 | elseif [X,Y]==[33,33] 291 | call TxbKey('o') 292 | else 293 | echon w:txbi '-' line('.') 294 | en 295 | elseif !(X && Y && s:pX && s:pY) 296 | elseif exists('w:txbi') 297 | sil call s:nav(s:mps[s:pX-X],line('w0')+s:mps[s:pY-Y]) 298 | echon w:txbi '-' line('.') 299 | else 300 | exe 'norm!'.s:panYCmd[s:pY-Y].s:panXCmd[s:pX-X] 301 | en 302 | let s:pX=X 303 | let s:pY=Y 304 | while getchar(0) isnot 0 305 | endwhile 306 | endfun 307 | 308 | fun! s:formatPar(str,w,...) 309 | let trspace=repeat(' ',len(&brk)) 310 | let spaces=repeat(' ',a:w+2) 311 | let ret=[] 312 | for par in split(a:str,"\n") 313 | let tick=0 314 | while ticktick 317 | call add(ret,a:0? par[tick :ix].spaces[1:a:w-ix+tick-1] : par[tick :ix]) 318 | let tick=ix 319 | while par[tick] is ' ' 320 | let tick+=1 321 | endwhile 322 | else 323 | call add(ret,strpart(par,tick,a:w)) 324 | let tick+=a:w 325 | en 326 | endw 327 | call add(ret,a:0? par[tick :].spaces[1:a:w-len(par)+tick] : par[tick :]) 328 | endfor 329 | return ret 330 | endfun 331 | 332 | "loadk() ret Get setting and load into ret (required for settings ui) 333 | "apply(arg) msg When setting is changed, apply; optionally return str msg (required for settings ui) 334 | "doc (str) What the setting does 335 | "getDef() arg Load default value into arg 336 | "check(arg) msg Normalize arg (eg convert from str to num) return msg (str if error, else num 0) 337 | "getInput() arg Overwrite default (let arg=input('New value:')) [c]hange behavior 338 | "save (bool) t:txb.setting[key] will always exist (via getDef(), or '' if getDef() is undefined); unsaved keys will be filtered out from t:txb.settings 339 | "onInit() Exe when loading plane 340 | let s:option = {'hist': {'doc': 'Jump history', 341 | \'getDef': 'let arg=[1,[0,0]]', 342 | \'check': 'let msg=type(arg)!=3 || len(arg)<2 || type(arg[0]) || arg[0]>=len(arg)? "Badly formed history" : 0', 343 | \'onInit': "if len(dict.hist)<98\n 344 | \elseif dict.hist[0]>0 && dict.hist[0]32? [32]+dict.hist[dict.hist[0]-32+1 : dict.hist[0]] : dict.hist[:dict.hist[0]])+dict.hist[dict.hist[0]+1 : (dict.hist[0]+322? 0 : ''Split width must be > 2''', 382 | \'apply': 'let t:txb.size[w:txbi]=arg|call s:redraw()'}, 383 | \'hotkey': {'doc': "Global hotkey. Examples: '', '' (ctrl-v), 'vx' (v then x). WARNING: If the hotkey becomes inaccessible, :call TxbKey('S')", 384 | \'loadk': 'let ret=g:TXB_HOTKEY', 385 | \'getDef': 'let arg=''''', 386 | \'save': 1, 387 | \'apply': "if escape(maparg(g:TXB_HOTKEY),'|')==?s:hotkeyArg\n 388 | \exe 'silent! nunmap' g:TXB_HOTKEY\n 389 | \elseif escape(maparg(''),'|')==?s:hotkeyArg\n 390 | \silent! nunmap \n 391 | \en\n 392 | \let g:TXB_HOTKEY=arg\n 393 | \exe 'nn ' g:TXB_HOTKEY s:hotkeyArg"}, 394 | \'mouse pan speed': {'doc': 'Pan speed[N] steps for every N mouse steps (only applies in terminal and ttymouse=xterm2 or sgr)', 395 | \'loadk': 'let ret=g:TXBMPS', 396 | \'getDef': 'let arg=[0,1,2,4,7,10,15,21,24,27]', 397 | \'check': "if type(arg)==1\n 398 | \try\n 399 | \let temp=eval(arg)\n 400 | \catch\n 401 | \let temp=''\n 402 | \endtry\n 403 | \unlet! arg\n 404 | \let arg=temp\n 405 | \en\n 406 | \let msg=type(arg)!=3? 'Must evaluate to list, eg, [0,1,2,3]' : arg[0]? 'First element must be 0' : 0", 407 | \'apply': "let g:TXBMPS=arg\n 408 | \let s:mps=g:TXBMPS+repeat([g:TXBMPS[-1]],40)+repeat([-g:TXBMPS[-1]],40)+map(reverse(copy(g:TXBMPS[1:])),'-v:val')\n 409 | \let s:panYCmd=['']+map(copy(g:TXBMPS[1:]),'v:val.''\''')+repeat([g:TXBMPS[-1].'\'],40)+repeat([g:TXBMPS[-1].'\'],40)+map(reverse(copy(g:TXBMPS[1:])),'v:val.''\''')\n 410 | \let s:panXCmd=['g']+map(copy(g:TXBMPS[1:]),'v:val.''zl''')+repeat([g:TXBMPS[-1].'zl'],40)+repeat([g:TXBMPS[-1].'zh'],40)+map(reverse(copy(g:TXBMPS[1:])),'v:val.''zh''')"}, 411 | \'label marker': {'doc': 'Regex for map marker, default ''txb:''. Labels are found via search(''^''.labelmark)', 412 | \'loadk': 'let ret=dict[''label marker'']', 413 | \'getDef': 'let arg=''txb:''', 414 | \'save': 1, 415 | \'getInput': "let newMarker=input('New label marker: ',disp[key])\n 416 | \let newAutotext=input('Label autotext (hotkey L; should be same as marker if marker doesn''t contain regex): ',newMarker)\n 417 | \if !empty(newMarker) && !empty(newAutotext)\n 418 | \let arg=newMarker\n 419 | \let dict['label autotext']=newAutotext\n 420 | \en", 421 | \'apply': 'let dict[''label marker'']=arg'}, 422 | \'label autotext': {'doc': 'Text for insert label command (hotkey L)', 423 | \'getDef': 'let arg=''txb:''', 424 | \'save': 1}, 425 | \'lines per map grid': {'doc': 'Lines mapped by each map line', 426 | \'loadk': 'let ret=dict[''lines per map grid'']', 427 | \'getDef': 'let arg=45', 428 | \'check': 'let arg=str2nr(arg)|let msg=arg>0? 0 : ''Lines per map grid must be > 0''', 429 | \'save': 1, 430 | \'apply': 'let dict[''lines per map grid'']=arg|call s:getMapDis()'}, 431 | \'map cell width': {'doc': 'Display width of map column', 432 | \'loadk': 'let ret=dict[''map cell width'']', 433 | \'getDef': 'let arg=5', 434 | \'check': 'let arg=str2nr(arg)|let msg=arg>2? 0 : ''Map cell width must be > 2''', 435 | \'save': 1, 436 | \'onInit': 'let t:mapw=dict["map cell width"]', 437 | \'apply': 'let dict[''map cell width'']=arg|let t:mapw=arg|call s:getMapDis()'}, 438 | \'split width': {'doc': 'Default split width (for appended splits, (c)hange for prompt to resize current splits)', 439 | \'loadk': 'let ret=dict[''split width'']', 440 | \'getDef': 'let arg=60', 441 | \'check': "let arg=str2nr(arg)|let msg=arg>2? 0 : 'Default split width must be > 2'", 442 | \'save': 1, 443 | \'apply': "if 'y'==?input('Apply new default width to current splits? (y/n)')\n 444 | \let t:txb.size=repeat([arg],t:txbL)\n 445 | \let msg='(All splits resized)'\n 446 | \else\n 447 | \let msg='(Only newly appended splits will inherit new width)'\n 448 | \en\n 449 | \let dict['split width']=arg"}, 450 | \'writefile': {'doc': 'Default settings save file', 451 | \'loadk': 'let ret=dict[''writefile'']', 452 | \'check': 'let msg=type(arg)==1? 0 : "Writefile must be string"', 453 | \'save': 1, 454 | \'apply':'let dict[''writefile'']=arg'}, 455 | \'working dir': {'doc': 'Directory assumed when loading splits with relative paths', 456 | \'loadk': 'let ret=dict["working dir"]', 457 | \'getDef': 'let arg=fnamemodify(getcwd(),":p")', 458 | \'check': "let [msg, arg]=isdirectory(arg)? [0,fnamemodify(arg,':p')] : ['Not a valid directory',arg]", 459 | \'onInit': 'let t:cwd="cd ".fnameescape(dict["working dir"])', 460 | \'save': 1, 461 | \'getInput': "let arg=input('Working dir (do not escape spaces; must be absolute path; press tab for completion): ',type(disp[key])==1? disp[key] : string(disp[key]),'file')", 462 | \'apply': "let msg='(Working dir not changed)'\n 463 | \if 'y'==?input('Are you sure you want to change the working directory? (Step 1/3) (y/n)')\n 464 | \let confirm=input('Step 2/3 (Recommended): Would you like to convert current files to absolute paths so that their locations remain unaffected? (y/n/cancel)')\n 465 | \if confirm==?'y' || confirm==?'n'\n 466 | \let confirm2=input('Step 3/3: Would you like to write a copy of the current plane to file, just in case? (y/n/cancel)')\n 467 | \if confirm2==?'y' || confirm2==?'n'\n 468 | \let curwd=getcwd()\n 469 | \if confirm2=='y'\n 470 | \exe g:txbCmd.W\n 471 | \en\n 472 | \if confirm=='y'\n 473 | \exe t:cwd\n 474 | \call map(t:txb.name,'fnamemodify(v:val,'':p'')')\n 475 | \en\n 476 | \let dict['working dir']=arg\n 477 | \let t:cwd='cd '.fnameescape(arg)\n 478 | \exe t:cwd\n 479 | \let t:bufs=map(copy(t:txb.name),'bufnr(fnamemodify(v:val,'':p''),1)')\n 480 | \exe 'cd' fnameescape(curwd)\n 481 | \let msg='(Working dir changed)'\n 482 | \en\n 483 | \en\n 484 | \en"}} 485 | let arg=exists('TXBMPS') && type(TXBMPS)==3 && TXBMPS[0]==0? TXBMPS : [0,1,2,4,7,10,15,21,24,27,30] 486 | exe s:option['mouse pan speed'].apply 487 | 488 | fun! s:settingsPager(dict,entry,attr) 489 | let applyCmd="if empty(arg)\n 490 | \let msg='Input cannot be empty'\n 491 | \else\n 492 | \exe get(a:attr[key],'check','let msg=0')\n 493 | \en\n 494 | \if (msg is 0) && (arg!=#disp[key])\n 495 | \let undo[key]=get(undo,key,disp[key])\n 496 | \exe a:attr[key].apply\n 497 | \let disp[key]=arg\n 498 | \en\n 499 | \en" 500 | let case={68: "if !has_key(disp,key) || !has_key(a:attr[key],'getDef')\n 501 | \let msg='No default defined for this value'\n 502 | \else\n 503 | \unlet! arg\n 504 | \exe a:attr[key].getDef\n".applyCmd, 505 | \85: "if !has_key(disp,key) || !has_key(undo,key)\n 506 | \let msg='No undo defined for this value'\n 507 | \else\n 508 | \unlet! arg\n 509 | \let arg=undo[key]\n".applyCmd, 510 | \99: "if has_key(disp,key)\n 511 | \unlet! arg\n 512 | \exe get(a:attr[key],'getInput','let arg=input(''Enter new value: '',type(disp[key])==1? disp[key] : string(disp[key]))')\n".applyCmd, 513 | \113: "let continue=0", 514 | \27: "let continue=0", 515 | \106: 'let s:spCursor+=1', 516 | \107: 'let s:spCursor-=1', 517 | \103: 'let s:spCursor=0', 518 | \71: 'let s:spCursor=entries-1'} 519 | call extend(case,{13:case.99,10:case.99}) 520 | let dict=a:dict 521 | let entries=len(a:entry) 522 | let [chsav,&ch]=[&ch,entries+3>11? 11 : entries+3] 523 | let s:spCursor=!exists('s:spCursor')? 0 : s:spCursor<0? 0 : s:spCursor>=entries? entries-1 : s:spCursor 524 | let s:spOff=!exists('s:spOff')? 0 : s:spOff<0? 0 : s:spOff>entries-&ch? (entries-&ch>=0? entries-&ch : 0) : s:spOff 525 | let s:spOff=s:spOffs:spCursor? s:spCursor : s:spOff 526 | let undo={} 527 | let disp={} 528 | for key in filter(copy(a:entry),'has_key(a:attr,v:val)') 529 | unlet! ret 530 | exe a:attr[key].loadk 531 | let disp[key]=ret 532 | endfor 533 | let [helpw,contentw]=&co>120? [60,60] : [&co/2,&co/2-1] 534 | let pad=repeat(' ',contentw) 535 | let msg=0 536 | let continue=1 537 | let settingshelp='jkgG:dn,up,top,bot (c)hange (U)ndo (D)efault (q)uit' 538 | let errlines=[] 539 | let doclines=s:formatPar(settingshelp,helpw) 540 | while continue 541 | redr! 542 | for [scrPos,i,key] in map(range(&ch),'[v:val,v:val+s:spOff,get(a:entry,v:val+s:spOff,"")]') 543 | let line=has_key(disp,key)? ' '.key.' : '.(type(disp[key])==1? disp[key] : string(disp[key])) : key 544 | if i==s:spCursor 545 | echohl Visual 546 | elseif !has_key(a:attr,key) 547 | echohl Title 548 | en 549 | if scrPos 550 | echon "\n" 551 | en 552 | if scrPos=contentw 554 | echon line[:contentw-1] 555 | else 556 | echon line 557 | echohl 558 | echon pad[:contentw-len(line)-1] 559 | en 560 | if scrPos=entries? entries-1 : s:spCursor 575 | let s:spOff=s:spOffs:spCursor? s:spCursor : s:spOff 576 | let errlines=msg is 0? [] : s:formatPar(msg,helpw) 577 | let doclines=errlines+s:formatPar(validkey? get(get(a:attr,a:entry[s:spCursor],{}),'doc',settingshelp) : settingshelp,helpw) 578 | endwhile 579 | let &ch=chsav 580 | redr 581 | echo 582 | endfun 583 | 584 | nno TxbY[ :call getmouse() 585 | nno TxbY :call getchar() 586 | nno TxbZ :call getchar() 587 | fun! getchar() 588 | if getchar(1) is 0 589 | sleep 1m 590 | call feedkeys("\TxbY") 591 | else 592 | call s:dochar() 593 | en 594 | endfun 595 | "mouse leftdown leftdrag leftup scrollup scrolldn 596 | "xterm 32 35 96 97 597 | "xterm2 32 64 35 96 97 598 | "sgr 0M 32M 0m 64 65 599 | "msStat 1 2 3 4 5 else 0 600 | fun! getmouse() 601 | if &ttymouse=~?'xterm' 602 | let s:msStat=[getchar(0)*0+getchar(0),getchar(0)-32,getchar(0)-32] 603 | let s:msStat[0]=s:msStat[0]==64? 2 : s:msStat[0]==32? 1 : s:msStat[0]==35? 3 : s:msStat[0]==96? 4 : s:msStat[0]==97? 5 : 0 604 | elseif &ttymouse==?'sgr' 605 | let s:msStat=split(join(map([getchar(0)*0+getchar(0),getchar(0),getchar(0),getchar(0),getchar(0),getchar(0),getchar(0),getchar(0),getchar(0),getchar(0),getchar(0)],'type(v:val)? v:val : nr2char(v:val)'),''),';') 606 | let s:msStat=len(s:msStat)> 2? [str2nr(s:msStat[0]).s:msStat[2][len(s:msStat[2])-1],str2nr(s:msStat[1]),str2nr(s:msStat[2])] : [0,0,0] 607 | let s:msStat[0]=s:msStat[0]==#'32M'? 2 : s:msStat[0]==#'0M'? 1 : (s:msStat[0]==#'0m' || s:msStat[0]==#'32K') ? 3 : s:msStat[0][:1]==#'64'? 4 : s:msStat[0][:1]==#'65'? 5 : 0 608 | else 609 | let s:msStat=[0,0,0] 610 | en 611 | while getchar(0) isnot 0 612 | endwhile 613 | call g:TxbKeyHandler(-1) 614 | endfun 615 | fun! s:dochar() 616 | let [k,c]=['',getchar()] 617 | while c isnot 0 618 | let k.=type(c)==0? nr2char(c) : c 619 | let c=getchar(0) 620 | endwhile 621 | call g:TxbKeyHandler(k) 622 | endfun 623 | 624 | fun! s:setCursor(l,vc,ix) 625 | let wt=getwinvar(1,'txbi') 626 | let wb=wt+winnr('$')-1 627 | if a:ixwb 631 | winc b 632 | exe 'norm! '.(a:lwinwidth(0)? '0g$' : '0'.a:vc.'|') 641 | en 642 | endfun 643 | 644 | fun! s:goto(sp,ln,...) 645 | let sp=(a:sp%t:txbL+t:txbL)%t:txbL 646 | let dln=a:ln>0? a:ln : 1 647 | let doff=a:0? a:1 : t:txb.size[sp]>&co? 0 : -(&co-t:txb.size[sp])/2 648 | let dsp=sp 649 | while doff<0 650 | let dsp=dsp>0? dsp-1 : t:txbL-1 651 | let doff+=t:txb.size[dsp-1]+1 652 | endwhile 653 | while doff>t:txb.size[dsp] 654 | let doff-=t:txb.size[dsp]+1 655 | let dsp=dsp>=t:txbL-1? 0 : dsp+1 656 | endwhile 657 | exe 'only|b'.t:bufs[dsp] 658 | let w:txbi=dsp 659 | if a:0 660 | exe 'norm! '.dln.(doff>0? 'zt0'.doff.'zl' : 'zt0') 661 | call s:redraw() 662 | else 663 | exe 'norm! 0'.(doff>0? doff.'zl' : '') 664 | call s:redraw() 665 | exe ((sp-getwinvar(1,'txbi')+1+t:txbL)%t:txbL).'wincmd w' 666 | let dif=line('w0')-(dln>winheight(0)/2? dln-winheight(0)/2 : 1) 667 | exe dif>0? 'norm! '.dif."\".dln.'G' : dif<0? 'norm! '.-dif."\".dln.'G' : dln 668 | en 669 | if t:jhist[t:jhist[0]][0]==sp && abs(t:jhist[t:jhist[0]][1]-dln)<23 670 | elseif t:jhist[0]1 692 | if win0==1 && !&wrap 693 | let offset=virtcol('.')-wincol() 694 | if offset=1 704 | let colt=colt? colt-1 : t:txbL-1 705 | let remain-=t:txb.size[colt]+1 706 | let colsLeft+=1 707 | endwhile 708 | let colb=w:txbi 709 | let remain=&co-(split0>0? split0+1+t:txb.size[w:txbi] : min([winwidth(1),t:txb.size[w:txbi]]) ) 710 | let colsRight=1 711 | while remain>=2 712 | let colb=(colb+1)%t:txbL 713 | let colsRight+=1 714 | let remain-=t:txb.size[colb]+1 715 | endwhile 716 | let colbw=t:txb.size[colb]+remain 717 | else 718 | let colt=w:txbi 719 | let colsLeft=0 720 | let colb=w:txbi 721 | let offset=&wrap? 0 : virtcol('.')-wincol() 722 | let remain=&co-max([2,t:txb.size[w:txbi]-offset]) 723 | let colsRight=1 724 | while remain>=2 725 | let colb=(colb+1)%t:txbL 726 | let colsRight+=1 727 | let remain-=t:txb.size[colb]+1 728 | endwhile 729 | let colbw=t:txb.size[colb]+remain 730 | en 731 | let dif=colsLeft-win0+1 732 | if dif>0 733 | let colt=(w:txbi-win0+t:txbL)%t:txbL 734 | for i in range(dif) 735 | let colt=colt? colt-1 : t:txbL-1 736 | exe 'to vert sb' t:bufs[colt] 737 | let w:txbi=colt 738 | exe t:txb.exe[colt] 739 | endfor 740 | elseif dif<0 741 | winc t 742 | for i in range(-dif) 743 | exe 'hide' 744 | endfor 745 | en 746 | let numcols=colsRight+colsLeft 747 | let dif=numcols-winnr('$') 748 | if dif>0 749 | let nextcol=((colb-dif)%t:txbL+t:txbL)%t:txbL 750 | for i in range(dif) 751 | let nextcol=(nextcol+1)%t:txbL 752 | exe 'bo vert sb' t:bufs[nextcol] 753 | let w:txbi=nextcol 754 | exe t:txb.exe[nextcol] 755 | endfor 756 | elseif dif<0 757 | winc b 758 | for i in range(-dif) 759 | exe 'hide' 760 | endfor 761 | en 762 | windo se nowfw 763 | winc = 764 | winc b 765 | let ccol=colb 766 | let changedsplits={} 767 | for i in range(1,numcols) 768 | se wfw 769 | exe 'b' t:bufs[ccol] 770 | let w:txbi=ccol 771 | exe t:txb.exe[ccol] 772 | if a:0 773 | let changedsplits[ccol]=1 774 | let t:txb.depth[ccol]=line('$') 775 | let t:txb.map[ccol]={} 776 | norm! 1G0 777 | let searchPat='^'.t:txb.settings['label marker'].'\zs' 778 | let line=search(searchPat,'Wc') 779 | while line 780 | let L=getline('.') 781 | let lnum=strpart(L,col('.')-1,6) 782 | if lnum!=0 783 | let lbl=lnum[len(lnum+0)]==':'? split(L[col('.')+len(lnum+0)+1:],'#',1) : [] 784 | if lnum=lnum 786 | let lbl=["! Error ".get(lbl,0,''),'ErrorMsg'] 787 | else 788 | exe 'norm! kd'.(line-lnum==1? 'd' : (line-lnum-1).'k') 789 | en 790 | elseif lnum>line 791 | exe 'norm! '.(lnum-line)."O\ej" 792 | en 793 | let line=line('.') 794 | else 795 | let lbl=split(L[col('.'):],'#',1) 796 | en 797 | if !empty(lbl) && !empty(lbl[0]) 798 | let t:txb.map[ccol][line]=[lbl[0],get(lbl,1,'')] 799 | en 800 | let line=search(searchPat,'W') 801 | endwhile 802 | en 803 | if i==numcols 804 | let offset=t:txb.size[colt]-winwidth(1)-virtcol('.')+wincol() 805 | exe !offset || &wrap? '' : offset>0? 'norm! '.offset.'zl' : 'norm! '.-offset.'zh' 806 | elseif i==1 807 | let dif=colbw-winwidth(0) 808 | exe 'vert res'.(dif>=0? '+'.dif : dif) 809 | norm! 0 810 | else 811 | let dif=t:txb.size[ccol]-winwidth(0) 812 | exe 'vert res'.(dif>=0? '+'.dif : dif) 813 | norm! 0 814 | en 815 | if s:badSync 816 | 1 817 | en 818 | winc h 819 | let ccol=ccol? ccol-1 : t:txbL-1 820 | endfor 821 | if !empty(changedsplits) 822 | call s:getMapDis(keys(changedsplits)) 823 | en 824 | se scrollopt=ver,jump 825 | silent exe "norm! :syncbind\" 826 | exe bufwinnr(pos[0]).'winc w' 827 | let offset=virtcol('.')-wincol() 828 | exe 'norm!' pos[1].'zt'.pos[2].'G'.(pos[3]<=offset? offset+1 : pos[3]>offset+winwidth(0)? offset+winwidth(0) : pos[3]) 829 | endfun 830 | 831 | fun! s:nav(N,L) 832 | let ei=&ei 833 | se ei=WinEnter,WinLeave,BufEnter,BufLeave 834 | let cBf=bufnr('') 835 | let cVc=virtcol('.') 836 | let cL0=line('w0') 837 | let cL=line('.') 838 | let align='norm! '.cL0.'zt' 839 | let resync=0 840 | let extrashift=0 841 | if a:N<0 842 | let N=-a:N 843 | if N<&co 844 | while winwidth(winnr('$'))<=N 845 | winc b 846 | let extrashift=(winwidth(0)==N) 847 | hide 848 | endw 849 | else 850 | winc t 851 | only 852 | en 853 | if winwidth(0)!=&co 854 | winc t 855 | let topw=winwidth(0) 856 | if winwidth(winnr('$'))<=N+3+extrashift || winnr('$')>=9 857 | se nowfw 858 | winc b 859 | exe 'vert res-'.(N+extrashift) 860 | winc t 861 | if winwidth(1)==1 862 | winc l 863 | se nowfw 864 | winc t 865 | exe 'vert res+'.(N+extrashift) 866 | winc l 867 | se wfw 868 | winc t 869 | elseif winwidth(0)==topw 870 | exe 'vert res+'.(N+extrashift) 871 | en 872 | se wfw 873 | else 874 | exe 'vert res+'.(N+extrashift) 875 | en 876 | se nowfw scrollopt=jump 877 | while winwidth(0)>=t:txb.size[w:txbi]+2 878 | let nextcol=w:txbi? w:txbi-1 : t:txbL-1 879 | exe 'to' winwidth(0)-t:txb.size[w:txbi]-1 'vsp|b' t:bufs[nextcol] 880 | let w:txbi=nextcol 881 | exe t:txb.exe[nextcol] 882 | if !&scb 883 | elseif line('$')0? 'norm! '.offset.'zl' : 'norm! '.-offset.'zh' 896 | let cWn=bufwinnr(cBf) 897 | if cWn==-1 898 | winc b 899 | norm! 0g$ 900 | elseif cWn!=1 901 | exe cWn.'winc w' 902 | exe cVc>=winwidth(0)? 'norm! 0g$' : 'norm! '.cVc.'|' 903 | en 904 | else 905 | let tcol=w:txbi 906 | let loff=&wrap? -N-extrashift : virtcol('.')-wincol()-N-extrashift 907 | if loff>=0 908 | exe 'norm! '.(N+extrashift).(bufwinnr(cBf)==-1? 'zhg$' : 'zh') 909 | else 910 | let [loff,extrashift]=loff==-1? [loff-1,extrashift+1] : [loff,extrashift] 911 | while loff<=-2 912 | let tcol=tcol? tcol-1 : t:txbL-1 913 | let loff+=t:txb.size[tcol]+1 914 | endwhile 915 | se scrollopt=jump 916 | exe 'b' t:bufs[tcol] 917 | let w:txbi=tcol 918 | exe t:txb.exe[tcol] 919 | if &scb 920 | if line('$')0? loff.'zl' : '') 928 | if t:txb.size[tcol]-loff<&co-1 929 | let spaceremaining=&co-t:txb.size[tcol]+loff 930 | let nextcol=(tcol+1)%t:txbL 931 | se nowfw scrollopt=jump 932 | while spaceremaining>=2 933 | exe 'bo' spaceremaining-1 'vsp|b' t:bufs[nextcol] 934 | let w:txbi=nextcol 935 | exe t:txb.exe[nextcol] 936 | if &scb 937 | if line('$')=winwidth(0)? 'norm! 0g$' : 'norm! '.cVc.'|' 954 | else 955 | norm! 0g$ 956 | en 957 | en 958 | en 959 | let extrashift=-extrashift 960 | elseif a:N>0 961 | let tcol=getwinvar(1,'txbi') 962 | let loff=winwidth(1)==&co? (&wrap? (t:txb.size[tcol]>&co? t:txb.size[tcol]-&co+1 : 0) : virtcol('.')-wincol()) : (t:txb.size[tcol]>winwidth(1)? t:txb.size[tcol]-winwidth(1) : 0) 963 | let N=a:N 964 | let botalreadysized=0 965 | if N>=&co 966 | let loff=winwidth(1)==&co? loff+&co : winwidth(winnr('$')) 967 | if loff>=t:txb.size[tcol] 968 | let loff=0 969 | let tcol=(tcol+1)%t:txbL 970 | en 971 | let toshift=N-&co 972 | if toshift>=t:txb.size[tcol]-loff+1 973 | let toshift-=t:txb.size[tcol]-loff+1 974 | let tcol=(tcol+1)%t:txbL 975 | while toshift>=t:txb.size[tcol]+1 976 | let toshift-=t:txb.size[tcol]+1 977 | let tcol=(tcol+1)%t:txbL 978 | endwhile 979 | if toshift==t:txb.size[tcol] 980 | let N+=1 981 | let extrashift=-1 982 | let tcol=(tcol+1)%t:txbL 983 | let loff=0 984 | else 985 | let loff=toshift 986 | en 987 | elseif toshift==t:txb.size[tcol]-loff 988 | let N+=1 989 | let extrashift=-1 990 | let tcol=(tcol+1)%t:txbL 991 | let loff=0 992 | else 993 | let loff+=toshift 994 | en 995 | se scrollopt=jump 996 | exe 'b' t:bufs[tcol] 997 | let w:txbi=tcol 998 | exe t:txb.exe[tcol] 999 | if &scb 1000 | if line('$')0? loff.'zl' : '') 1009 | else 1010 | if winwidth(1)==1 1011 | let cWn=winnr() 1012 | winc t 1013 | hide 1014 | let N-=2 1015 | if N<=0 1016 | if cWn!=1 1017 | exe (cWn-1).'winc w' 1018 | else 1019 | 1winc w 1020 | norm! 0 1021 | en 1022 | exe cL 1023 | let dif=line('w0')-a:L 1024 | exe dif>0? 'norm! '.dif."\" : dif<0? 'norm! '.-dif."\" : '' 1025 | let &ei=ei 1026 | return 1027 | en 1028 | en 1029 | let shifted=0 1030 | let w1=winwidth(1) 1031 | while w1<=N-botalreadysized 1032 | let w2=winwidth(2) 1033 | let extrashift=w1==N 1034 | let shifted=w1+1 1035 | winc t 1036 | hide 1037 | if winwidth(1)==w2 1038 | let botalreadysized+=w1+1 1039 | en 1040 | let tcol=(tcol+1)%t:txbL 1041 | let loff=0 1042 | let w1=winwidth(1) 1043 | endw 1044 | let N+=extrashift 1045 | let loff+=N-shifted 1046 | en 1047 | let ww1=winwidth(1) 1048 | if ww1!=&co 1049 | let N=N-botalreadysized 1050 | if N 1051 | winc b 1052 | exe 'vert res+'.N 1053 | if virtcol('.')!=wincol() 1054 | norm! 0 1055 | en 1056 | winc t 1057 | if winwidth(1)!=ww1-N 1058 | exe 'vert res'.(ww1-N) 1059 | en 1060 | en 1061 | while winwidth(winnr('$'))>=t:txb.size[getwinvar(winnr('$'),'txbi')]+2 1062 | winc b 1063 | se nowfw scrollopt=jump 1064 | let nextcol=(w:txbi+1)%t:txbL 1065 | exe 'bo' winwidth(0)-t:txb.size[w:txbi]-1 'vsp|b' t:bufs[nextcol] 1066 | let w:txbi=nextcol 1067 | exe t:txb.exe[nextcol] 1068 | if &scb 1069 | if line('$')0? 'norm! '.offset.'zl' : 'norm! '.-offset.'zh' 1084 | let cWn=bufwinnr(cBf) 1085 | if cWn==-1 1086 | norm! g0 1087 | elseif cWn!=1 1088 | exe cWn.'winc w' 1089 | exe cVc>=winwidth(0)? 'norm! 0g$' : 'norm! '.cVc.'|' 1090 | else 1091 | exe (cVc=2 1094 | let spaceremaining=&co-t:txb.size[tcol]+loff 1095 | se nowfw scrollopt=jump 1096 | while spaceremaining>=2 1097 | let nextcol=(w:txbi+1)%t:txbL 1098 | exe 'bo' spaceremaining-1 'vsp|b' t:bufs[nextcol] 1099 | let w:txbi=nextcol 1100 | exe t:txb.exe[nextcol] 1101 | if &scb 1102 | if line('$')=winwidth(0) 1120 | norm! 0g$ 1121 | else 1122 | exe 'norm! '.cVc.'|' 1123 | en 1124 | else 1125 | winc t 1126 | exe (cVc0? 'norm! '.offset.'zl' : 'norm! '.-offset.'zh' 1131 | let cWn=bufwinnr(cBf) 1132 | if cWn==-1 1133 | norm! g0 1134 | elseif cWn!=1 1135 | exe cWn.'winc w' 1136 | if cVc>=winwidth(0) 1137 | norm! 0g$ 1138 | else 1139 | exe 'norm! '.cVc.'|' 1140 | en 1141 | else 1142 | exe (cVc" 1151 | en 1152 | exe cL 1153 | let dif=line('w0')-a:L 1154 | exe dif>0? 'norm! '.dif."\" : dif<0? 'norm! '.-dif."\" : '' 1155 | let &ei=ei 1156 | return extrashift 1157 | endfun 1158 | 1159 | fun! s:getMapDis(...) 1160 | let poscell=repeat(' ',t:mapw) 1161 | let negcell=repeat('.',t:mapw) 1162 | let gran=t:txb.settings["lines per map grid"] 1163 | if !a:0 1164 | let t:bgd=map(range(0,max(t:txb.depth)+gran,gran),'join(map(range(t:txbL),v:val.''>t:txb.depth[v:val]? "'.negcell.'" : "'.poscell.'"''),'''')') 1165 | let t:deepR=len(t:bgd)-1 1166 | let t:disTxt=copy(t:bgd) 1167 | let t:disClr=eval('['.join(repeat(['[""]'],t:deepR+1),',').']') 1168 | let t:disIx=eval('['.join(repeat(['[98989]'],t:deepR+1),',').']') 1169 | let t:gridClr=eval('['.join(repeat(['{}'],t:txbL),',').']') 1170 | let t:gridLbl=deepcopy(t:gridClr) 1171 | let t:gridPos=deepcopy(t:gridClr) 1172 | let t:oldDepth=copy(t:txb.depth) 1173 | en 1174 | let newR={} 1175 | for sp in a:0? a:1 : range(t:txbL) 1176 | let newD=t:txb.depth[sp]/gran 1177 | while newD>len(t:bgd)-1 1178 | call add(t:bgd,repeat('.',t:txbL*t:mapw)) 1179 | call add(t:disIx,[98989]) 1180 | call add(t:disClr,['']) 1181 | call add(t:disTxt,'') 1182 | let newR[len(t:bgd)-1]=1 1183 | endwhile 1184 | let i=t:oldDepth[sp]/gran 1185 | let colIx=sp*t:mapw 1186 | while i>newD 1187 | let t:bgd[i]=colIx? t:bgd[i][:colIx-1].negcell.t:bgd[i][colIx+t:mapw :] : negcell.t:bgd[i][colIx+t:mapw :] 1188 | let newR[i]=1 1189 | let i-=1 1190 | endwhile 1191 | while i<=newD 1192 | let t:bgd[i]=colIx? t:bgd[i][:colIx-1].poscell.t:bgd[i][colIx+t:mapw :] : poscell.t:bgd[i][colIx+t:mapw :] 1193 | let newR[i]=1 1194 | let i+=1 1195 | endwhile 1196 | let t:oldDepth[sp]=t:txb.depth[sp] 1197 | let conflicts={} 1198 | let splitLbl={} 1199 | let splitClr={} 1200 | let splitPos={} 1201 | for j in keys(t:txb.map[sp]) 1202 | let r=j/gran 1203 | if has_key(splitLbl,r) 1204 | if has_key(conflicts,r) 1205 | elseif splitLbl[r][0][0]=='!' 1206 | let conflicts[r]=[splitLbl[r][0],splitPos[r][0]] 1207 | let splitPos[r]=[] 1208 | else 1209 | let conflicts[r]=['$',0] 1210 | en 1211 | if t:txb.map[sp][j][0][0]=='!' && t:txb.map[sp][j][0]=0 1257 | let l=len(get(get(t:gridLbl[j],i,[]),0,'')) 1258 | if !l 1259 | let padl+=t:mapw 1260 | elseif l>=padl 1261 | if empty(t:disTxt[i]) 1262 | let t:disTxt[i]=t:gridLbl[j][i][0] 1263 | let intervals=[padl] 1264 | let t:disClr[i]=[t:gridClr[j][i]] 1265 | else 1266 | let t:disTxt[i]=t:gridLbl[j][i][0][:padl-2].'#'.t:disTxt[i] 1267 | if t:gridClr[j][i]==t:disClr[i][0] 1268 | let intervals[0]+=padl 1269 | else 1270 | call insert(intervals,padl) 1271 | call insert(t:disClr[i],t:gridClr[j][i]) 1272 | en 1273 | en 1274 | let padl=t:mapw 1275 | elseif empty(t:disTxt[i]) 1276 | let t:disTxt[i]=t:gridLbl[j][i][0].strpart(t:bgd[i],j*t:mapw+l,padl-l) 1277 | if empty(t:gridClr[j][i]) 1278 | let intervals=[padl] 1279 | let t:disClr[i]=[''] 1280 | else 1281 | let intervals=[l,padl-l] 1282 | let t:disClr[i]=[t:gridClr[j][i],''] 1283 | en 1284 | let padl=t:mapw 1285 | else 1286 | let t:disTxt[i]=t:gridLbl[j][i][0].strpart(t:bgd[i],j*t:mapw+l,padl-l).t:disTxt[i] 1287 | if empty(t:disClr[i][0]) 1288 | let intervals[0]+=padl-l 1289 | else 1290 | call insert(intervals,padl-l) 1291 | call insert(t:disClr[i],'') 1292 | en 1293 | if empty(t:gridClr[j][i]) 1294 | let intervals[0]+=l 1295 | else 1296 | call insert(intervals,l) 1297 | call insert(t:disClr[i],t:gridClr[j][i]) 1298 | en 1299 | let padl=t:mapw 1300 | en 1301 | let j-=1 1302 | endw 1303 | if empty(get(t:gridLbl[0],i,'')) 1304 | let padl-=t:mapw 1305 | if empty(t:disTxt[i]) 1306 | let t:disTxt[i]=strpart(t:bgd[i],0,padl) 1307 | let intervals=[padl] 1308 | let t:disClr[i]=[''] 1309 | else 1310 | let t:disTxt[i]=strpart(t:bgd[i],0,padl).t:disTxt[i] 1311 | if empty(t:disClr[i][0]) 1312 | let intervals[0]+=padl 1313 | else 1314 | call insert(intervals,padl) 1315 | call insert(t:disClr[i],'') 1316 | en 1317 | en 1318 | en 1319 | let sum=0 1320 | for j in range(len(intervals)) 1321 | let intervals[j]=sum+intervals[j] 1322 | let sum=intervals[j] 1323 | endfor 1324 | let t:disIx[i]=intervals 1325 | let t:disIx[i][-1]=98989 1326 | endfor 1327 | endfun 1328 | 1329 | fun! s:ecMap() 1330 | let xe=s:mCoff+&co-2 1331 | let b=s:mC*t:mapw 1332 | if b=s:mCoff? 0 : s:mCoff-b 1336 | let trunce=truncb+xe-b 1337 | let vxe=b-1 1338 | else 1339 | let sele=-999999 1340 | en 1341 | let i=s:mRoff>0? s:mRoff : 0 1342 | let lastR=i+&ch-2>t:deepR? t:deepR : i+&ch-2 1343 | while i<=lastR 1344 | let j=0 1345 | if isele 1346 | while t:disIx[i][j]xe 1351 | echon t:disTxt[i][s:mCoff : xe] "\n" 1352 | else 1353 | echon t:disTxt[i][s:mCoff : t:disIx[i][j]-1] 1354 | let j+=1 1355 | while t:disIx[i][j]vxe 1371 | echon t:disTxt[i][s:mCoff : vxe] 1372 | else 1373 | echon t:disTxt[i][s:mCoff : t:disIx[i][j]-1] 1374 | let j+=1 1375 | while t:disIx[i][j]xe 1395 | echon t:disTxt[i][vOff : xe] "\n" 1396 | else 1397 | echon t:disTxt[i][vOff : t:disIx[i][j]-1] 1398 | let j+=1 1399 | while t:disIx[i][j]TxbY") 1423 | return 1424 | en 1425 | let [&ch,&more,&ls,&stal]=s:mSavSettings 1426 | return s:mExit==2 && s:goto(s:mC,get(t:gridPos[s:mC],s:mR,[s:mR*t:txb.settings['lines per map grid']])[0]) 1427 | elseif s:msStat[0]==2 && s:mPrevCoor[0] && s:mPrevCoor[0]<3 1428 | let s:mRoff=s:mRoff-s:msStat[2]+s:mPrevCoor[2] 1429 | let s:mCoff=s:mCoff-s:msStat[1]+s:mPrevCoor[1] 1430 | let s:mRoff=s:mRoff<0? 0 : s:mRoff>t:deepR? t:deepR : s:mRoff 1431 | let s:mCoff=s:mCoff<0? 0 : s:mCoff>=t:txbL*t:mapw? t:txbL*t:mapw-1 : s:mCoff 1432 | call s:ecMap() 1433 | elseif s:msStat[0]>3 1434 | let s:mRoff+=4*(s:msStat[0]==5)-2 1435 | let s:mRoff=s:mRoff<0? 0 : s:mRoff>t:deepR? t:deepR : s:mRoff 1436 | cal s:ecMap() 1437 | elseif s:msStat[0]!=3 1438 | elseif s:msStat==[3,1,1] 1439 | let [&ch,&more,&ls,&stal]=s:mSavSettings 1440 | return 1441 | elseif s:mPrevCoor[0]!=1 1442 | elseif &ttymouse=='xterm' && s:mPrevCoor[1:]!=s:msStat[1:] 1443 | let s:mRoff=s:mRoff-s:msStat[2]+s:mPrevCoor[2] 1444 | let s:mCoff=s:mCoff-s:msStat[1]+s:mPrevCoor[1] 1445 | let s:mRoff=s:mRoff<0? 0 : s:mRoff>t:deepR? t:deepR : s:mRoff 1446 | let s:mCoff=s:mCoff<0? 0 : s:mCoff>=t:txbL*t:mapw? t:txbL*t:mapw-1 : s:mCoff 1447 | call s:ecMap() 1448 | else 1449 | let s:mR=s:msStat[2]-&lines+&ch-1+s:mRoff 1450 | let s:mC=(s:msStat[1]-1+s:mCoff)/t:mapw 1451 | let s:mR=s:mR<0? 0 : s:mR>t:deepR? t:deepR : s:mR 1452 | let s:mC=s:mC<0? 0 : s:mC>=t:txbL? t:txbL-1 : s:mC 1453 | if [s:mR,s:mC]==s:mPrevClk 1454 | let [&ch,&more,&ls,&stal]=s:mSavSettings 1455 | call s:goto(s:mC,get(t:gridPos[s:mC],s:mR,[s:mR*t:txb.settings['lines per map grid']])[0]) 1456 | return 1457 | en 1458 | let s:mPrevClk=[s:mR,s:mC] 1459 | call s:ecMap() 1460 | echon s:mC '-' s:mR*t:txb.settings['lines per map grid'] 1461 | en 1462 | let s:mPrevCoor=copy(s:msStat) 1463 | call feedkeys("\TxbY") 1464 | endfun 1465 | 1466 | let s:mCase={"\e":"let s:mExit=0|redr", 1467 | \"\":'exe g:txbCmd["\"]|ec mes|cal getchar()|redr!', 1468 | \'q':"let s:mExit=0", 1469 | \'h':"let s:mC=s:mC>s:mCount? s:mC-s:mCount : 0", 1470 | \'l':"let s:mC=s:mC+s:mCounts:mCount? s:mR-s:mCount : 0", 1473 | \'H':"let s:mCoff=s:mCoff>s:mCount*t:mapw? s:mCoff-s:mCount*t:mapw : 0|let s:mCount='01'", 1474 | \'L':"let s:mCoff=s:mCoff+s:mCount*t:mapws:mCount? s:mRoff-s:mCount : 0|let s:mCount='01'", 1477 | \'1':"let s:mCount=s:mCount is '01'? 1 : s:mCount.'1'", 1478 | \'2':"let s:mCount=s:mCount is '01'? 2 : s:mCount.'2'", 1479 | \'3':"let s:mCount=s:mCount is '01'? 3 : s:mCount.'3'", 1480 | \'4':"let s:mCount=s:mCount is '01'? 4 : s:mCount.'4'", 1481 | \'5':"let s:mCount=s:mCount is '01'? 5 : s:mCount.'5'", 1482 | \'6':"let s:mCount=s:mCount is '01'? 6 : s:mCount.'6'", 1483 | \'7':"let s:mCount=s:mCount is '01'? 7 : s:mCount.'7'", 1484 | \'8':"let s:mCount=s:mCount is '01'? 8 : s:mCount.'8'", 1485 | \'9':"let s:mCount=s:mCount is '01'? 9 : s:mCount.'9'", 1486 | \'0':"let s:mCount=s:mCount is '01'? '01' : s:mCount.'0'", 1487 | \'c':"let s:mR=s:mRoff+(&ch-2)/2\n 1488 | \let s:mC=(s:mCoff+&co/2)/t:mapw\n 1489 | \let s:mR=s:mR>t:deepR? t:deepR : s:mR\n 1490 | \let s:mC=s:mC>=t:txbL? t:txbL-1 : s:mC", 1491 | \'C':"let s:mRoff=s:mR-(&ch-2)/2\n 1492 | \let s:mCoff=s:mC*t:mapw-&co/2", 1493 | \'z':"call s:ecMap()\n 1494 | \let input=str2nr(input('File lines per map line (>=10): ',t:txb.settings['lines per map grid']))\n 1495 | \let width=str2nr(input('Width of map column (>=1): ',t:mapw))\n 1496 | \if input<1 || width<1\n 1497 | \echoerr 'Granularity, width must be > 0'\n 1498 | \sleep 500m\n 1499 | \redr!\n 1500 | \elseif input!=t:txb.settings['lines per map grid'] || width!=t:mapw\n 1501 | \let s:mR=s:mR*t:txb.settings['lines per map grid']/input\n 1502 | \let s:mRoff=s:mR>(&ch-2)/2? s:mR-(&ch-2)/2 : 0\n 1503 | \let t:txb.settings['lines per map grid']=input\n 1504 | \let t:txb.settings['lines per map grid']=input\n 1505 | \let t:mapw=width\n 1506 | \let s:mCoff=s:mC*t:mapw>&co/2? s:mC*t:mapw-&co/2 : 0\n 1507 | \call s:getMapDis()\n 1508 | \let s:mPrevClk=[0,0]\n 1509 | \redr!\n 1510 | \en\n", 1511 | \'g':'let s:mExit=2', 1512 | \'p':"let t:jhist[0]=max([t:jhist[0]-s:mCount,1])\n 1513 | \let [s:mC,s:mR]=[t:jhist[t:jhist[0]][0],t:jhist[t:jhist[0]][1]/t:txb.settings['lines per map grid']]\n 1514 | \let mapmes=' '.t:jhist[0].'/'.(len(t:jhist)-1)\n 1515 | \let s:mC=s:mC<0? 0 : s:mC>=t:txbL? t:txbL-1 : s:mC\n 1516 | \let s:mR=s:mR<0? 0 : s:mR>t:deepR? t:deepR : s:mR\n 1517 | \let s:mCount='01'", 1518 | \'P':"let t:jhist[0]=min([t:jhist[0]+s:mCount,len(t:jhist)-1])\n 1519 | \let [s:mC,s:mR]=[t:jhist[t:jhist[0]][0],t:jhist[t:jhist[0]][1]/t:txb.settings['lines per map grid']]\n 1520 | \let mapmes=' '.t:jhist[0].'/'.(len(t:jhist)-1)\n 1521 | \let s:mC=s:mC<0? 0 : s:mC>=t:txbL? t:txbL-1 : s:mC\n 1522 | \let s:mR=s:mR<0? 0 : s:mR>t:deepR? t:deepR : s:mR\n 1523 | \let s:mCount='01'"} 1524 | call extend(s:mCase, 1525 | \{'y':s:mCase.h.'|'.s:mCase.k, 'u':s:mCase.l.'|'.s:mCase.k, 'b':s:mCase.h.'|'.s:mCase.j, 'n':s:mCase.l.'|'.s:mCase.j, 1526 | \ 'Y':s:mCase.H.'|'.s:mCase.K, 'U':s:mCase.L.'|'.s:mCase.K, 'B':s:mCase.H.'|'.s:mCase.J, 'N':s:mCase.L.'|'.s:mCase.J}) 1527 | for i in split('h j k l y u b n p P C') 1528 | let s:mCase[i].="\nlet s:mCount='01'\n 1529 | \let s:mCoff=s:mCoff>=s:mC*t:mapw? s:mC*t:mapw : s:mCoffs:mR? s:mR : s:mRoff" 1531 | endfor 1532 | call extend(s:mCase,{"\":s:mCase.g,"\":s:mCase.l,"\":s:mCase.h,"\":s:mCase.j,"\":s:mCase.k," ":s:mCase.J,"\":s:mCase.K}) 1533 | 1534 | let s:count='03' 1535 | fun! TxbKey(cmd) 1536 | let g:TxbKeyHandler=function("s:doCmdKeyhandler") 1537 | call s:doCmdKeyhandler(a:cmd) 1538 | endfun 1539 | fun! s:doCmdKeyhandler(c) 1540 | exe get(g:txbCmd,a:c,'let mes="(0..9) count (f1) help (hjklyubn) move (r)edraw (M)ap all (o)pen map (A)ppend (D)elete (L)abel (S)ettings (W)rite settings (q)uit"') 1541 | if mes is ' ' 1542 | echon '? ' w:txbi '.' line('.') ' ' str2nr(s:count) ' ' strtrans(a:c) 1543 | call feedkeys("\TxbZ") 1544 | elseif !empty(mes) 1545 | redr|echon '# ' mes 1546 | en 1547 | endfun 1548 | 1549 | let txbCmd={'S':"let mes=''\ncall call('s:settingsPager',exists('w:txbi')? [t:txb.settings,['Global','hotkey','mouse pan speed','Plane','split width','autoexe','lines per map grid','map cell width','working dir','label marker','Split '.w:txbi,'current width','current autoexe','current file'],s:option] : [{},['Global','hotkey','mouse pan speed'],s:option])", 1550 | \'o':"let mes=''\n 1551 | \let s:mCount='01'\n 1552 | \let s:mSavSettings=[&ch,&more,&ls,&stal]\n 1553 | \let [&more,&ls,&stal]=[0,0,0]\n 1554 | \let &ch=&lines\n 1555 | \let s:mPrevClk=[0,0]\n 1556 | \let s:mPrevCoor=[0,0,0]\n 1557 | \let s:mR=line('.')/t:txb.settings['lines per map grid']\n 1558 | \call s:redraw(1)\n 1559 | \redr!\n 1560 | \let s:mR=s:mR>t:deepR? t:deepR : s:mR\n 1561 | \let s:mC=w:txbi\n 1562 | \let s:mC=s:mC<0? 0 : s:mC>=t:txbL? t:txbL-1 : s:mC\n 1563 | \let s:mExit=1\n 1564 | \let s:mRoff=s:mR>(&ch-2)/2? s:mR-(&ch-2)/2 : 0\n 1565 | \let s:mCoff=s:mC*t:mapw>&co/2? s:mC*t:mapw-&co/2 : 0\n 1566 | \call s:ecMap()\n 1567 | \let g:TxbKeyHandler=function('s:mapKeyHandler')\n 1568 | \if t:jhist[t:jhist[0]][0]==s:mC && abs(t:jhist[t:jhist[0]][1]-line('.'))<23\n 1569 | \elseif t:jhist[0]TxbY\")\n", 1576 | \'M':"if 'y'==?input('? Entirely build map by scanning all files? (Map always partially updates on (o)pening and (r)edrawing) (y/n): ')\n 1577 | \let curwin=exists('w:txbi')? w:txbi : 0\n 1578 | \let view=winsaveview()\n 1579 | \for i in map(range(t:txbL),'(curwin+v:val)%t:txbL')\n 1580 | \exe 'b' t:bufs[i]\n 1581 | \let t:txb.depth[i]=line('$')\n 1582 | \let t:txb.map[i]={}\n 1583 | \exe 'norm! 1G0'\n 1584 | \let searchPat='^'.t:txb.settings['label marker'].'\\zs'\n 1585 | \let line=search(searchPat,'Wc')\n 1586 | \while line\n 1587 | \let L=getline('.')\n 1588 | \let lnum=strpart(L,col('.')-1,6)\n 1589 | \if lnum!=0\n 1590 | \let lbl=lnum[len(lnum+0)]==':'? split(L[col('.')+len(lnum+0)+1:],'#',1) : []\n 1591 | \if lnum=lnum\n 1593 | \let lbl=[' Error! '.get(lbl,0,''),'ErrorMsg']\n 1594 | \else\n 1595 | \exe 'norm! kd'.(line-lnum==1? 'd' : (line-lnum-1).'k')\n 1596 | \en\n 1597 | \elseif lnum>line\n 1598 | \exe 'norm! '.(lnum-line).'O\ej'\n 1599 | \en\n 1600 | \let line=line('.')\n 1601 | \else\n 1602 | \let lbl=split(L[col('.'):],'#',1)\n 1603 | \en\n 1604 | \if !empty(lbl) && !empty(lbl[0])\n 1605 | \let t:txb.map[i][line]=[lbl[0],get(lbl,1,'')]\n 1606 | \en\n 1607 | \let line=search(searchPat,'W')\n 1608 | \endwhile\n 1609 | \endfor\n 1610 | \exe 'b' t:bufs[curwin]\n 1611 | \call winrestview(view)\n 1612 | \call s:getMapDis()\n 1613 | \call s:redraw()\n 1614 | \let mes='Plane remapped'\n 1615 | \else\n 1616 | \let mes='Plane remap cancelled'\n 1617 | \en", 1618 | \"\":"let warnings=(v:version<=703? '\n# Vim 7.4 is recommended.': '') 1619 | \.(v:version<703 || v:version==703 && !has('patch30')? '\n# Vim < 7.3.30: Plane can''t be automatically backed up in viminfo; use hotkey W instead.' 1620 | \: empty(&vi) || stridx(&vi,'!')==-1? '\n# Put '':set viminfo+=!'' in your .vimrc file to remember plane between sessions (or write to file with hotkey W)' : '') 1621 | \.(has('gui_running')? '\n# In gVim, auto-redrawing on resize is disabled because resizing occurs too frequently in gVim. Use hotkey r or '':call TxbKey(''r'')'' instead' : '') 1622 | \.(has('gui_running') || !(has('unix') || has('vms'))? '\n# gVim and non-unix terminals do not support mouse in map mode' 1623 | \: &ttymouse!=?'xterm2' && &ttymouse!=?'sgr'? '\n# '':set ttymouse=xterm2'' or ''sgr'' allows mouse panning in map mode.' : '')\n 1624 | \let warnings=(empty(warnings)? 'WARNINGS (none)' : 'WARNINGS '.warnings).'\n\nTIPS\n# Note the '': '' when both label anchor and title are supplied.\n 1625 | \# The map is updated on hotkey o, r, or M. On update, displaced labels are reanchored by inserting or removing preceding blank lines. Anchoring failures are highlighted in the map.\n 1626 | \# :call TxbKey(''S'') to access settings if the hotkey becomes inaccessible.\n 1627 | \# When a title starts with ''!'' (eg, ''txb:321: !Title'') it will be shown instead of other labels occupying the same cell.\n 1628 | \# Keyboard-free navigation: in normal mode, dragging to the top left corner opens the map and clicking the top left corner of the map closes it. (ttymouse=sgr or xterm2 only)\n 1629 | \# Initializing a plane while the cursor is in a file in the plane will restore plane to that location.\n 1630 | \# Label highlighting:\n:syntax match Title +^txb\\S*: \\zs.[^#\\n]*+ oneline display'\n 1631 | \let commands='microViche 1.8.4.2 6/2014 HOTKEY '.g:TXB_HOTKEY.'\n\n 1632 | \HOTKEY COMMANDS MAP COMMANDS (hotkey o)\n 1633 | \hjklyubn Pan (takes count) hjklyubn Move (takes count)\n 1634 | \r / M Redraw visible / all HJKLYUBN Pan (takes count)\n 1635 | \A / D Append / Delete split g 2click Go\n 1636 | \S / W Settings / Write to file click / drag Select / pan\n 1637 | \o Open map z Zoom\n 1638 | \L Label c / C Center cursor / view\n 1639 | \ Help Help\n 1640 | \q Quit q Quit\n 1641 | \ p / P Prev / next jump\n\n 1642 | \LABEL marker(anchor)(:)( title)(#highlght)(#comment)\n 1643 | \txb:345 bla bla Anchor only\ntxb:345: Title#Visual Anchor, title, color\n 1644 | \txb: Title Title only\ntxb: Title##bla bla Title only'\n 1645 | \if &co>71+45\n 1646 | \let blanks=repeat(' ',71)\n 1647 | \let col1=s:formatPar(commands,71,1)\n 1648 | \let col2=s:formatPar(warnings,&co-71-3>71? 71 : &co-71-3)\n 1649 | \let mes='\n'.join(map(range(len(col1)>len(col2)? len(col1) : len(col2)),\"get(col1,v:val,blanks).get(col2,v:val,'')\"),'\n')\n 1650 | \else\n 1651 | \let mes='\n'.commands.'\n\n'.warnings\n 1652 | \en", 1653 | \'q':"let mes=' '", 1654 | \-1:"let mes=''", 1655 | \'null':'let mes=" "', 1656 | \'h':"let mes=' '|let s:count='0'.str2nr(s:count)|sil call s:nav(-s:count,line('w0'))|redrawstatus!", 1657 | \'j':"let mes=' '|let s:count='0'.str2nr(s:count)|sil call s:nav(0,line('w0')+s:count)|redrawstatus!", 1658 | \'k':"let mes=' '|let s:count='0'.str2nr(s:count)|sil call s:nav(0,line('w0')-s:count)|redrawstatus!", 1659 | \'l':"let mes=' '|let s:count='0'.str2nr(s:count)|sil call s:nav(s:count,line('w0'))|redrawstatus!", 1660 | \'y':"let mes=' '|let s:count='0'.str2nr(s:count)|sil call s:nav(-s:count,line('w0')-s:count)|redrawstatus!", 1661 | \'u':"let mes=' '|let s:count='0'.str2nr(s:count)|sil call s:nav(s:count,line('w0')-s:count)|redrawstatus!", 1662 | \'b':"let mes=' '|let s:count='0'.str2nr(s:count)|sil call s:nav(-s:count,line('w0')+s:count)|redrawstatus!", 1663 | \'n':"let mes=' '|let s:count='0'.str2nr(s:count)|sil call s:nav(s:count,line('w0')+s:count)|redrawstatus!", 1664 | \1:"let mes=' '|let s:count=s:count[0] is '0'? 1 : s:count.'1'", 1665 | \2:"let mes=' '|let s:count=s:count[0] is '0'? 2 : s:count.'2'", 1666 | \3:"let mes=' '|let s:count=s:count[0] is '0'? 3 : s:count.'3'", 1667 | \4:"let mes=' '|let s:count=s:count[0] is '0'? 4 : s:count.'4'", 1668 | \5:"let mes=' '|let s:count=s:count[0] is '0'? 5 : s:count.'5'", 1669 | \6:"let mes=' '|let s:count=s:count[0] is '0'? 6 : s:count.'6'", 1670 | \7:"let mes=' '|let s:count=s:count[0] is '0'? 7 : s:count.'7'", 1671 | \8:"let mes=' '|let s:count=s:count[0] is '0'? 8 : s:count.'8'", 1672 | \9:"let mes=' '|let s:count=s:count[0] is '0'? 9 : s:count.'9'", 1673 | \0:"let mes=' '|let s:count=s:count[0] is '0'? '01': s:count.'0'", 1674 | \'L':"let L=getline('.')\n 1675 | \let mes='Labeled'\n 1676 | \if -1==match(L,'^'.t:txb.settings['label autotext'])\n 1677 | \let prefix=t:txb.settings['label autotext'].line('.').' '\n 1678 | \call setline(line('.'),prefix.L)\n 1679 | \call cursor(line('.'),len(prefix))\n 1680 | \startinsert\n 1681 | \elseif setline(line('.'),substitute(L,'^'.t:txb.settings['label autotext'].'\\zs\\d*\\ze',line('.'),''))\nen", 1682 | \'D':"redr\n 1683 | \if t:txbL==1\n 1684 | \let mes='Cannot delete last split!'\n 1685 | \elseif input('Really delete current column (y/n)? ')==?'y'\n 1686 | \call remove(t:txb.name,w:txbi)\n 1687 | \call remove(t:bufs,w:txbi)\n 1688 | \call remove(t:txb.size,w:txbi)\n 1689 | \call remove(t:txb.exe,w:txbi)\n 1690 | \call remove(t:txb.map,w:txbi)\n 1691 | \call remove(t:gridLbl,w:txbi)\n 1692 | \call remove(t:txb.depth,w:txbi)\n 1693 | \call remove(t:oldDepth,w:txbi)\n 1694 | \call remove(t:gridClr,w:txbi)\n 1695 | \call remove(t:gridPos,w:txbi)\n 1696 | \let t:txbL=len(t:txb.name)\n 1697 | \call s:getMapDis()\n 1698 | \winc W\n 1699 | \let cpos=[line('.'),virtcol('.'),w:txbi]\n 1700 | \call s:redraw()\n 1701 | \let mes='Split deleted'\n 1702 | \en\n 1703 | \call s:setCursor(cpos[0],cpos[1],cpos[2])", 1704 | \'A':"let cpos=[line('.'),virtcol('.'),w:txbi]\n 1705 | \exe t:cwd\n 1706 | \let file=input('(Use full path if not in working directory '.t:txb.settings['working dir'].')\nAppend file (do not escape spaces) : ',t:txb.name[w:txbi],'file')\n 1707 | \if empty(file)\n 1708 | \let mes='Cancelled'\n 1709 | \else\n 1710 | \let mes='[' . file . (index(t:txb.name,file)==-1? '] appended.' : '] (duplicate) appended.')\n 1711 | \call insert(t:txb.name,file,w:txbi+1)\n 1712 | \call insert(t:bufs,bufnr(fnamemodify(file,':p'),1),w:txbi+1)\n 1713 | \call insert(t:txb.size,t:txb.settings['split width'],w:txbi+1)\n 1714 | \call insert(t:txb.exe,t:txb.settings.autoexe,w:txbi+1)\n 1715 | \call insert(t:txb.map,{},w:txbi+1)\n 1716 | \call insert(t:txb.depth,100,w:txbi+1)\n 1717 | \call insert(t:oldDepth,100,w:txbi+1)\n 1718 | \call insert(t:gridLbl,{},w:txbi+1)\n 1719 | \call insert(t:gridClr,{},w:txbi+1)\n 1720 | \call insert(t:gridPos,{},w:txbi+1)\n 1721 | \let t:txbL=len(t:txb.name)\n 1722 | \call s:redraw(1)\n 1723 | \call s:getMapDis()\n 1724 | \en\n 1725 | \cd -\n 1726 | \call s:setCursor(cpos[0],cpos[1],cpos[2])", 1727 | \'W':"exe t:cwd\n 1728 | \let input=input('? Write plane to file (relative to '.t:txb.settings['working dir'].'): ',t:txb.settings.writefile,'file')\n 1729 | \let [t:txb.settings.writefile,mes]=empty(input)? [t:txb.settings.writefile,'File write aborted'] : [input,writefile(['let TXB='.substitute(string(t:txb),'\n','''.\"\\\\n\".''','g'),'call TxbInit(TXB)'],input)? 'Error: File not writable' : 'File written, '':source '.input.''' to restore']\n 1730 | \cd -", 1731 | \'r':"call s:redraw(1)|redr|let mes='Redraw complete'"} 1732 | call extend(txbCmd,{"\":txbCmd.l,"\":txbCmd.h,"\":txbCmd.j,"\":txbCmd.k,"\e":txbCmd.q}) 1733 | --------------------------------------------------------------------------------