├── 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 |
--------------------------------------------------------------------------------