My vimrc, the philosophy of vim

I want here to upload my vimrc, piece by piece, and then move on to the philosophy of vim scripting, which is actually right on course.

Now, I write almost exclusively on a smart phone, a Droid 3 — the most advanced slider phone with a replaceable battery — and I use vim almost exclusively to write. There will be a few settings that are smart phone specific. There are basically 7 parts to my vimrc:

1) General settings, intializations, etc — included here for completeness.

se viminfo=!,'100,<50,s10,h
if !exists('au_processed')
	let au_processed=1
	au VimEnter * call VimEntered()
	au BufRead *.txt call InitTextFile()
	au BufNewFile *.txt call InitTextFile() | exe "norm! i".localtime()." "
	\ .strftime('%y%m%d')." vim: set nowrap ts=4 tw=62 fo=aw:"
en
fun! VimEntered()
	se nowrap linebreak sidescroll=1 ignorecase smartcase incsearch backspace=2
	se tabstop=4 history=150 mouse=a ttymouse=xterm hidden listchars=tab:>\ ,eol:<
	se wildmode=list:longest,full display=lastline modeline t_Co=256
	se whichwrap+=h,l wildmenu sw=4
	syntax off
	cd /sdcard/q335writings | so abbrev
	if !exists("g:TMARK") | let g:TMARK=0 | endif
	if !exists("g:ST_ESCKY") | let g:ST_ESCKY='@' | endif
	exe 'no '.g:ST_ESCKY.' <Esc>'
	exe 'no! '.g:ST_ESCKY.' <Esc>'
	exe 'cno '.g:ST_ESCKY.' <C-C>'
	let g:fileL= exists('g:FILE_HIST') ? split(g:FILE_HIST) : []
	call InitFileL()
	if !argc() | e main.txt | en | call UpdFileL()
	au BufEnter * call UpdFileL()
	au BufLeave * call FileLAdd(expand('%'),line('.'))
	au VimLeavePre * let g:FILE_HIST=join([expand('%').'$'.line('.')]+g:fileL,"\n")
	map  [3~ 
	map! [3~ 
	map  OP !
	map! OP !
	no   OQ @
	no!  OQ @
	map  OR #
	map! OR #
	map  OS $
	map! OS $
	map  [15~ %
	map! [15~ %
	no   <F7> <PageDown>
	no!  <F7> <PageDown>
	no   <F8> <PageUp>
	no!  <F8> <PageUp>
	ino  <F9> <Home>
	ino  <F10> <End>
	nn   <F9> <C-O>
	nn   <F10> <C-I>
	map  [2~ <Del>
	map! [2~ <C-O>x
	hi clear MatchParen | hi MatchParen cterm=underline
	hi clear StatusLine | hi StatusLine cterm=underline
	hi clear StatusLineNC | hi StatusLineNC cterm=underline ctermfg=240
	se stl=\ %l.%02c/%L\ %<%f%=\ %{(localtime()-g:TMARK)/60.strftime('\ %H:%M\ %d')}\
endfun

2. A file history system. This remembers the last 30 or so files and the last cursor position in each file, it replaces buffer switching entirely. It also automatically assigns the relevant keys, so that pressing tab(to access the menu)-V will open up the last file that began with the letter V, such as .vimrc.

let CmdLb=["R)rm .swp","T)Timer","S)Toggle Status","H)Help","F)Fingerpaint",
\ "E)Edit","D)Delete History","@)Cancel"]
let CmdL=["'redr|!rm '.(expand('%:h')=='.'? '':expand('%:h').'/')"
\ .".(expand('%:t')[0]=='.'? '':'.').expand('%:t').'.swp'",
\ "'redr|let g:TMARK=localtime()|exe CmdMenu()'","'redr|se ls='.2*!(&ls==2)",
\ "'exe \"norm! vawly\"|exe \"h \".(@\"[-1:-1]==\"(\"? @\" : @\"[:-2])|redr'",
\ "'call Paint()'","'redr|e<cWORD>'","'redr|call DelMenu()'","'redr'"]
let Asc2CmdIx=repeat([-1],256)
for i in range(len(CmdLb))
	let Asc2CmdIx[char2nr(tolower(CmdLb[i][0]))]=i
	let Asc2CmdIx[char2nr(toupper(CmdLb[i][0]))]=i
endfor
let HLb=split('123456789abcdefghijklmnopqrstuvwxyz','\zs')
let Asc2HLb=repeat([-1],256)
for i in range(len(HLb))
	let Asc2HLb[char2nr(tolower(HLb[i]))]=i
	let Asc2HLb[char2nr(toupper(HLb[i]))]=i
endfor
let g:maxW=15
fun! InitFileL()
	let g:fileLb=map(range(len(g:fileL)),'matchstr(g:fileL[v:val],"[^/]*\\$")[:-2]')
	let g:HLb2fIx=repeat([-1],len(g:HLb)+1) "invar: g:HLb2fIx[-1]=-1
	let firstopenslot=0
	for i in range(len(g:fileLb))
		let g:fileLb[i]=len(g:fileLb[i])+3>g:maxW ? g:fileLb[i][0:g:maxW-8]."~".g:fileLb[i][-3:] : g:fileLb[i]
		let lbl=g:Asc2HLb[char2nr(g:fileLb[i][0])]
		if lbl==-1 || g:HLb2fIx[lbl]!=-1
			let lbl=match(g:HLb2fIx,-1,firstopenslot)
			let firstopenslot=lbl+1
		en
		let g:fileLb[i]=g:HLb[lbl].')'.g:fileLb[i]
		let g:HLb2fIx[lbl]=i
	endfor
endfun
fun! FileLAdd(name,num)
	if a:name==''|retu|en
	let g:fileL=[a:name.'$'.a:num]+g:fileL
	if len(g:fileL)>=len(g:HLb)-8
		let g:fileL=g:fileL[:g:HLb-18] | call InitFileL()
	retu|en
	let name=matchstr(a:name,"[^/]*\$")
	let name=len(name)+3>g:maxW ? name[0:g:maxW-8]."~".name[-3:] : name
	let lbl=g:Asc2HLb[char2nr(name[0])]
	let colIx=g:HLb2fIx[lbl]
	call map(g:HLb2fIx,'v:val==-1 ? -1 : (v:val+1)')
	if lbl==-1
		let newIx=match(g:HLb2fIx,-1)
		let g:HLb2fIx[newIx]=0
		let g:fileLb=[toupper(g:HLb[newIx]).')'.name]+g:fileLb
	elseif colIx!=-1
		let newIx=match(g:HLb2fIx,-1)
		let g:HLb2fIx[newIx]=colIx+1
		let g:HLb2fIx[lbl]=0
		let g:fileLb[colIx]=g:HLb[newIx].g:fileLb[colIx][1:]
		let g:fileLb=[toupper(name[0]).')'.name]+g:fileLb
	else
		let g:HLb2fIx[lbl]=0
		let g:fileLb=[toupper(g:HLb[lbl]).')'.name]+g:fileLb
	en
endfun
fun! FileLRem(ix)
	if a:ix>=len(g:fileL) || a:ix<0 | retu ''|en
	if g:fileLb[a:ix][0]==g:fileLb[a:ix][2]
		for i in range(a:ix+1,len(g:fileLb)-1)
			if g:fileLb[i][2]==g:fileLb[a:ix][0]
				let g:HLb2fIx[g:Asc2HLb[char2nr(g:fileLb[i][0])]]=-1
				let g:HLb2fIx[g:Asc2HLb[char2nr(g:fileLb[a:ix][0])]]=i
				let g:fileLb[i]=g:fileLb[a:ix][0].g:fileLb[i][1:]
			break|en
		endfor
	en
	call remove(g:fileLb,a:ix)
	call map(g:HLb2fIx,'v:val>=a:ix ? (v:val==a:ix ? -1 : v:val-1) : v:val')
	return remove(g:fileL,a:ix)
endfun
fun! UpdFileL()
	let lineN=split(FileLRem(match(g:fileL,'\V'.expand('%').'$')),'\$')
	if len(lineN)>=2 | exe 'norm! '.lineN[-1].'G' | en
endfun
fun! FmtList(list,tabW)
	let padN=[0]+range(a:tabW-1,1,-1)
	let ecstr=a:list[0] | let endX=len(ecstr)
	for e in a:list[1:]
		if endX+padN[endX%a:tabW]+len(e)>=&columns-1
			let ecstr.="\n".e | let endX=len(e)
		else
			let ecstr.=s:Pad[1:padN[endX%a:tabW]].e
			let endX+=padN[endX%a:tabW]+len(e)
		en
	endfor
	return ecstr
endfun
fun! Stl()
	let stl=' '.line('.').'.'.col('.').'/'.line('$').' '
	let p2=expand('%')
	let p3=' '.(localtime()-g:TMARK)/60.strftime(' %H:%M %d ')
	let pad=&columns-len(stl)-len(p2)-len(p3)-1
	return pad>=0 ? stl.p2.s:Pad[1:pad].p3 : stl.p2[(-pad):].p3
endfun
fun! CmdMenu()
	echoh StatusLine|ec Stl()|echoh None|ec FmtList(g:CmdLb,10)
	retu eval(g:CmdL[g:Asc2CmdIx[getchar()]])
endfun
fun! HistMenu()
	echoh StatusLine|ec Stl()|echoh None|ec FmtList(g:fileLb+['0)CMD'],g:maxW)
	let sel=getchar()|redr
	if sel==48
		retu CmdMenu()
	elseif sel==9
		retu 'e '.substitute(split(g:fileL[0],'\$')[0],"\ ",'\\ ',"g")
	else
		retu g:HLb2fIx[g:Asc2HLb[sel]]==-1 ? '' :
		\'e '.substitute(split(g:fileL[g:HLb2fIx[g:Asc2HLb[sel]]],'\$')[0],"\ ",'\\ ',"g")
	en
endfun
fun! DelMenu()
	echoh StatusLine|ec Stl()|echoh None|ec FmtList(["DELETE "]+g:fileLb,g:maxW)
	if FileLRem(g:HLb2fIx[g:Asc2HLb[getchar()]])!=''|redr|call DelMenu()| el|redr|en
endfun
nn <C-I> :exe HistMenu()<CR>

3. Mappings to insert or append a single character. This is something that I need to do surprisingly often and strangely absent from vim. For example, to insert a quotation mark, type <space>”.

fun! Repeatchar(char,count)
	return repeat(a:char,a:count)
endfun
nmap <C-J> <C-M>
nno <silent> <C-M> :<C-U>exec 'norm! a'.Repeatchar(nr2char(getchar()),v:count1)<CR>
nno <silent> <space> :<C-U>exec 'norm! i'.Repeatchar(nr2char(getchar()),v:count1)<CR>

4. A bunch of often used command mode shortcuts. Vim has “:wa” (write all) and “:wq” (write and quit), but not “:waq”, which is included below. Also included is “:ws” (write and source) and “:wd” (write and delete buffer), both of which are used very often.

cnorea <expr> we ((getcmdtype()==':' && getcmdpos()<4)? 'w\|e' :'we')
cnorea <expr> wf ((getcmdtype()==':' && getcmdpos()<4)? 'w\|e\|norm! gggqG':'we')
cnorea <expr> waq ((getcmdtype()==':' && getcmdpos()<5)? 'wa\|q':'waq')
cnorea <expr> ws ((getcmdtype()==':' && getcmdpos()<4)? 'w\|so%':'ws')
cnorea <expr> wd ((getcmdtype()==':' && getcmdpos()<4)? 'w\|bd':'wd')
cnorea <expr> wsd ((getcmdtype()==':' && getcmdpos()<5)? 'w\|so%\|bd':'wsd')

5. A modification of vim’s default search-for-single-char commands, f,t,F,T, to go across multiple lines, in the same way that vim’s search-for-patterns go across multiple lines. This is not only more intuitive but especially useful when working with prose that is auto-formatted by vim, which is my standard environment (ie, hard line breaks automatically inserted, no wrapping)

let g:PrevFT=[0,0]
fun! MultilineFT(command)
	if a:command==';'
		let com=g:PrevFT[0]
	elseif a:command==','
		let ascii=char2nr(g:PrevFT[0])
		let com=nr2char((ascii>95)*(ascii-32)+(ascii<=95)*(ascii+32))
	else
		let g:PrevFT=[a:command,nr2char(getchar())]
		let com=a:command
	endif
	if com==#'F'
		call search(g:PrevFT[1],'bW')
	elseif com==#'T'
		exe (search(g:PrevFT[1],'bW')? 'norm! l' : '')
	elseif com==#'f'
		exe (search(g:PrevFT[1],'W')? 'norm! l' : '')
	elseif com==#'t'
		call search(g:PrevFT[1],'W')
	endif
endfun
fun! MultilinenFT(command)
	if a:command==';'
		let com=g:PrevFT[0]
	elseif a:command==','
		let ascii=char2nr(g:PrevFT[0])
		let com=nr2char((ascii>95)*(ascii-32)+(ascii<=95)*(ascii+32))
	else
		let g:PrevFT=[a:command,nr2char(getchar())]
		let com=a:command
	endif
	if com==#'F'
		call search(g:PrevFT[1],'bW')
	elseif com==#'T'
		norm! h
		call search(g:PrevFT[1],'bW')
		norm! l
	elseif com==#'t'
		norm! l
		call search(g:PrevFT[1],'W')
		norm! h
	elseif com==#'f'
		call search(g:PrevFT[1],'W')
	endif
endfun
nn <silent> F :call MultilinenFT('F')<CR>
nn <silent> T :call MultilinenFT('T')<CR>
nn <silent> f :call MultilinenFT('f')<CR>
nn <silent> t :call MultilinenFT('t')<CR>
nn <silent> ; :call MultilinenFT(';')<CR>
nn <silent> , :call MultilinenFT(',')<CR>
ono <silent> F :call MultilineFT('F')<CR>
ono <silent> T :call MultilineFT('T')<CR>
ono <silent> f :call MultilineFT('f')<CR>
ono <silent> t :call MultilineFT('t')<CR>
ono <silent> ; :call MultilinenFT(';')<CR>
ono <silent> , :call MultilinenFT(',')<CR>

6. Autocapitalization after sentence breaks. Autocapitalizing “I”, “I’m”, etc is done via vim’s built in “abbrev” command, and also included below. This not only makes typing in vim consistent with the rest of the phone, but is incredibly helpful to have on a small thumbboard. Check out this wiki page for an explanation.

fun! CapWait(prev)
	redr
	let next=nr2char(getchar())
	if next=~'[.?!\r\n[:blank:]()]'
		exe 'normal! i' . next . "\<Right>"
		return CapWait(next)
	elseif next=~'[\e\@]'
	return "\<del>"
	elseif a:prev=~'[\r\n[:blank:]]'
		return toupper(next) . "\<del>"
	else
		return next . "\<del>"
	endif
endfun
fun! CapHere()
	let trunc = getline(".")[:col(".")-2]
	return col(".")==1 ? CapWait("\r")
	\ : trunc=~'[?!.]\s*$\|^\s*$' ? CapWait(trunc[-1:-1]) : "\<del>"
endfun
fun! InitTextFile()
	iab <buffer> i I
	iab <buffer> Id I'd
	iab <buffer> id I'd
	iab <buffer> im I'm
	iab <buffer> Im I'm
	ino <buffer> <silent> <F6> _<Esc>h?'<CR>x<C-O>i<Del>
	im <buffer> <silent> . ._<Left><C-R>=CapWait('.')<CR>
	im <buffer> <silent> ? ?_<Left><C-R>=CapWait('?')<CR>
	im <buffer> <silent> ! !_<Left><C-R>=CapWait('!')<CR>
	im <buffer> <silent> <CR> <CR>_<Left><C-R>=CapWait("\r")<R>
	im <buffer> <silent> <NL> <NL>_<Left><C-R>=CapWait("\n")<CR>
	nm <buffer> <silent> O O_<Left><C-R>=CapWait("\r")<CR>
	nm <buffer> <silent> o o_<Left><C-R>=CapWait("\r")<CR>
	nm <buffer> <silent> a a_<Left><C-R>=CapHere()<CR>
	nm <buffer> <silent> A $a_<Left><C-R>=CapHere()<CR>
	nm <buffer> <silent> i i_<Left><C-R>=CapHere()<CR>
	nm <buffer> <silent> I I_<Left><C-R>=CapHere()<CR>
	nm <buffer> <silent> s s_<Left><C-R>=CapHere()<CR>
	nm <buffer> <silent> cc cc_<Left><C-R>=CapHere()<CR>
	nm <buffer> <silent> cw cw_<Left><C-R>=CapHere()<CR>
	nm <buffer> <silent> R R_<Left><C-R>=CapHere()<CR>
	nm <buffer> <silent> C C_<Left><C-R>=CapHere()<CR>
	nno <buffer> <silent> > :se ai<CR>mt>apgqap't:se noai<CR>
	nno <buffer> <silent> < :se ai<CR>mt<apgqap't:se noai<CR>
	if getline(1)=~'tw='
		nmap <buffer> A }b$a
		nmap <buffer> I {w0i
	endif
endfun

7. A bunch of touchscreen optimizations for vim:
1) Hold and drag to scroll, like in a mobile web browser
2) Emulation of hold and drag to resize split windows — this turned out to be incredibly complicated, but it works well now
3) “Fingerpainting” in vim, as for creating ascii art
This code is not portable, as I hacked mouse support into the android version of vim: touch movement is tracked by sending left-clicks on mouse motions and mouse releases on touch release. Check out this google code page if you you want a version of vim with this hacked mouse support and a customizable font. (I highly, highly recommend Envy Code R! — it’s the font I’m married to.)

let s:Dashes=repeat('-',200)|let s:Pad=repeat(' ',200)
let s:Speed = range(1,25)
let g:MouseMode='InitScroll'
se wiw=1
fun! InitScroll()
	let s:vesave=&ve | se ve=all
	let s:pP=[winnr(),winline(),wincol()]
	let g:MouseMode='OnScroll'
	let s:initCol=s:pP[2]
endfun
fun! OnScroll()
	let s:cP=[winnr(),winline(),wincol()]
	if s:cP[0]==s:pP[0]
		if s:initCol
			let s:initCol=(abs(s:cP[2]-s:initCol)<10)*s:initCol
    		let difC=0
		else
    		let difC=s:cP[2]-s:pP[2]
		endif
		let difR=s:cP[1]-s:pP[1]
    	let s:pP=s:cP
		let cmd=(difC>0? difC."z\<left>":difC<0? (-difC)."z\<right>":'')
		\ .(difR>0? s:Speed[difR]."\<C-Y>":difR<0? s:Speed[-difR]."\<C-E>":'')
		if cmd
			exe 'norm! '.cmd
	    	redraw | echo s:Dashes[2:line('w0')*&columns/line('$')]
	    elseif line('.')==line('$')
	    	exe "norm! \<C-Y>"
	    endif
	else
		let g:MouseMode='OnResize'
		call OnResize()
	endif
endfun
fun! OnVisual()
	let cdiff=virtcol("'v")-wincol()
	let rdiff=line("'v")-line(".")
	echo rdiff.(s:Pad[1:(cdiff>0? wincol():virtcol("'v"))]
	\ .s:Dashes[1:abs(cdiff)])[len(rdiff):]
	if line('.')==line('w$')
		exe "norm! \<C-E>"
	elseif line('.')==line('w0')
		exe "norm! \<C-Y>"
	endif
endfun
let s:dirs=['k','j','l','h'] |let s:opp =['j','k','h','l']
fun! GetResDir()
	for i in (s:cP[0]>s:pP[0]? [1,2]:[0,3])
		exe s:cP[0].'winc w|winc '.s:opp[i]
		if winnr()==s:pP[0]
			return s:dirs[i]
		endif
	endfor
	return 'U'
endfun
fun! ResizeWinU(winnr,L)
endfun
fun! ResizeWinX(winnr,L)
endfun
fun! WinPushK(winnr,L)
	exe a:winnr.'winc w|winc k'
	let moved=0
	let iwin=a:winnr
	let todo=[]
	while iwin!=winnr() && a:L>moved
		let iwin=winnr()
		let curL=winheight(0)-1
		let moved+=insert(todo,[iwin,(curL>a:L-moved? a:L-moved : (curL>0)*curL)])[0][1]
		winc k
	endwhile
	let sum=0
	for i in todo
		let sum+=i[1]
		exe i[0].'winc w|res -'.sum
	endfor
endfun
fun! WinPullK(winnr,L)
	exe a:winnr.'winc w|winc k'
   	exe 'res +'.(winnr()!=a:winnr? min([winheight(a:winnr)-1,a:L]):0)
endfun
fun! WinPushH(winnr,L)
	exe a:winnr.'winc w|winc h'
	let moved=0
	let iwin=a:winnr
	let todo=[]
	while iwin!=winnr() && a:L>moved
		let iwin=winnr()
		let curL=winwidth(0)-1
		let moved+=insert(todo,[iwin,(curL>a:L-moved? a:L-moved : (curL>0)*curL)])[0][1]
		winc h
	endwhile
	let sum=0
	for i in todo
		let sum+=i[1]
		exe i[0].'winc w|vert res -'.sum
	endfor
endfun
fun! WinPullH(winnr,L)
	exe a:winnr.'winc w|winc h'
   	exe 'vert res +'.(winnr()!=a:winnr? min([winwidth(a:winnr)-1,a:L]):0)
endfun
fun! WinPushJ(winnr,L)
	exe a:winnr.'winc w|winc j'
	let moved=0
	let curwin=a:winnr
	while moved<a:L && winnr()!=curwin
		let moved+=winheight(0)-1
		let curwin=winnr()
		winc j
	endwhile
	exe a:winnr.'winc w|res +'.min([a:L,moved])
endfun
fun! WinPullJ(winnr,L)
	exe a:winnr.'winc w|winc j'
   	if winnr()!=a:winnr
		exe a:winnr.'winc w|res -'.min([winheight(a:winnr)-1,a:L])
   	endif
endfun
fun! WinPushL(winnr,L)
	exe a:winnr.'winc w|winc l'
	let moved=0
	let curwin=a:winnr
	while moved<a:L && winnr()!=curwin
		let moved+=winwidth(0)-1
		let curwin=winnr()
		winc l
	endwhile
	exe a:winnr.'winc w|vert res +'.min([a:L,moved])
endfun
fun! WinPullL(winnr,L)
	exe a:winnr.'winc w|winc l'
   	if winnr()!=a:winnr
		exe a:winnr.'winc w|vert res -'.min([winwidth(a:winnr)-1,a:L])
   	endif
endfun
fun! OnResize()
	let s:cP=[winnr(),winline(),wincol()]
	if s:pP[0]!=s:cP[0]
		let s:dir=GetResDir()
		if s:dir=='k'
			call WinPushK(s:pP[0],winheight(s:cP[0])-s:cP[1]+1)
			let s:pP[1]=1
		elseif s:dir=='j'
			call WinPushJ(s:pP[0],s:cP[1])
			let s:pP[1]=winheight(s:pP[0])
		elseif s:dir=='h'
			call WinPushH(s:pP[0],winwidth(s:cP[0])-s:cP[2]+1)
			let s:pP[2]=1
		elseif s:dir=='l'
			call WinPushL(s:pP[0],s:cP[2])
			let s:pP[2]=winwidth(s:pP[0])
		endif
	elseif s:pP!=s:cP
		if s:dir=='j'
			call WinPullJ(s:pP[0],winheight(s:cP[0])-s:cP[1])
			let s:pP[1]=winheight(s:pP[0])
		elseif s:dir=='k'
			call WinPullK(s:pP[0],s:cP[1]-1)
			let s:pP[1]=1
		elseif s:dir=='l'
			call WinPullL(s:pP[0],winwidth(s:cP[0])-s:cP[2])
			let s:pP[2]=winwidth(s:pP[0])
		elseif s:dir=='h'
			call WinPullH(s:pP[0],s:cP[2]-1)
			let s:pP[2]=1
		endif
	endif
endfun
fun! OnRelease()
	if g:MouseMode=='OnVisual'
		norm! v`v
	else
		exe 'se ve='.s:vesave
	endif
	let g:MouseMode='InitScroll'
endfun
fun! Paint()
	ec ' Brush? (Backspace to turn off)' | let brush=getchar()
	if brush!="\<BS>"
		let brush=nr2char(brush)
		let s:vesave=&ve | se ve=all
		exe 'nn <silent> <leftmouse> <leftmouse>R'.(brush=='|'? '\|' : brush)
		exe 'ino <silent> <leftmouse> <leftmouse>'.(brush=='|'? '\|' : brush)
		ino <leftrelease> <Esc>
		redr|ec brush
	else
		redr|ec ' Brush Off'
		exe 'se ve='.s:vesave
		nn <silent> <leftmouse> <leftmouse>:call {g:MouseMode}()<CR>
		nn <silent> <leftrelease> <leftmouse>:call OnRelease()<CR>
		try
			iunmap <leftrelease>
			iunmap <leftmouse>
		catch | endtry
	endif
endfun
nn <silent> <leftmouse> <leftmouse>:call {g:MouseMode}()<CR>
nn <silent> <leftrelease> <leftmouse>:call OnRelease()<CR>
vn <silent> <leftmouse> <Esc>mv<leftmouse>:let g:MouseMode='OnVisual'<CR>

And let’s move on to my theory of vim —

Vim scripting is incredibly addicting, it really satisfies some strange sort of craving, I enjoy it much more than the more useful or serious kinds of coding I’ve dabbled in. It brings me back to my very first class, in high school (taken at a local community college) on programming in C++. I was annoyed to learn that I would mostly be doing console programming, that I wouldn’t be able to make any awesome games — this is probably the usual experience. Of course, I didn’t really understand what computer programming really “was” in a sense, but I’m also somewhat bitter (right now) that no one took the time to explain it to me. Vim script, for an older, more mature me, seems to get at what computer programming ‘really is’. I know I am fudging words here but this is the intuition that this essay will concern itself with, we can call it maybe an effort to think about and “unfudge” this question: “What is scripting or coding, really?”

Vimscript is striking because it seems to break a great number of borders. For example, consider, this class of equivalent actions:
1) I can scroll to the 15th (from the 1st line) line: jjjjjjjjjjjjjjj
2) I can do it faster: 15j
3) I can tell the vim interpreter to scroll 15 lines: norm! 15j
4) I can tell the above teller to scroll a certain number of lines based on certain conditions: let lines=15|exe “norm !”.lines.”j”
5) And so on … “exe ‘let lines=15| …”

There is probably some technical word for this aspect of scripting languages, but what’s interesting here is that one seems to “code oneself”, or one seems to code by observing “oneself” — whatever this word may even mean at this point. It is really a “flattening” of all these figures. Vim scripting deals, it seems, indiscriminately with multiple layers of … management, or telling. What this really means to me is that there is really something beyond the figure, or more important than the figure, even though the figure is a kind of “bottleneck” — ie, we will always be thinking about the figure, there is no way around it — if we are to write a history, it will always be a history of figures.

I place emphasis on the “really” of our topic, “What is coding, really?” — suggesting that this question is related to a moment of honesty or to the more “humanistic” questions of authenticity, honesty, etc. Now, we are aware that we are always challenged by otherness — this is perhaps something we treat with a kind of blase attitude — and we are blase precisely because we are all to used to the terrible stories that people tell about their lives changing. In fact, in the very introduction, I wrote about vim changing my life, helping me reach maturity in fact, because with vim I can look back on my first class with bitterness, vim was the moment when I understood what coding really was. And this was because vim brought me into contact with certain figures, even though all of them appear to be substitutes for myself — but that’s what we call maturity, anyways, right? (Incidentally, the odd implication here is that the closer the other is, the more radical the consequences of the contact — so that one is changed the most by someone who is just like you.)

Vim script, in other words, helped me become a coder, ie, one who somehow “sought out the code” or “dwelled inside the code” as opposed to someone who looked towards the code to accomplish certain tasks. And this is something that is evident from the above snippets, since the code that I wrote there did not really accomplish anything so much as “modify” or “extend”, modify the home in which I dwelt. And, furthermore, the idea is that this change occurs through the entire series of collapsed figures — so that the one who plans, asks for, codes, solves, etc., are all in alignment, so that even at the macroscopic level I begin to be drawn towards problems that would satisfy the demands of this collapsed series of figures. (This kind of reminds me of that joke about a hotel being on fire and the mathematician who proclaimed groggily “A solution exists!” and jumped back into bed.)

We declared that the figure was the bottleneck, yet we do not want to say that it is the foundation. The question is the nature of the arising of these figures, which is itself not figural (ie, it’s not a matter of “realism” here). And lastly — and this may be to confuse things further — I’m reminded of that Benjamin quote about a historical heliotropism, where all of the past turns towards the rising sun in history. But basically, the entire difficulty here is looking beyond the figures, beyond the similarity between figures, towards that ground from which figures may potentially arise. The process of the birth of figures is related to a complicated process that we’ve been calling “isomorphism” (ie, the above “just like you”), but there must be some grander scheme controlling this process itself, which is the what Benjamin calls “the sun of history”.

Vim, we’ve been arguing for a long time, flattens or explodes the traditional figures, temporally arranged, perhaps, that are gathered about the process of coding. It does so by viewing coding not as the execution of ideas (ie, “temporally arranged”, from beginning to finish) but rather the manipulation of strings. The fascination with vim (the way in which we are held spellbound) is in the way in which the letters on the screen, as string, is always on the verge of exploding whatever home we have established.

 

 

Tags: , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s