Put it into your .vimrc
:
"" number text object
"" only "inner" text object: vin, din, cin
func! s:number_textobj()
let rx_num = '\d\+\(\.\d\+\)*'
if search(rx_num, 'ceW')
normal v
call search(rx_num, 'bcW')
endif
endfunc
xnoremap <silent> in :<C-u>call <sid>number_textobj()<CR>
onoremap in :<C-u>normal vin<CR>
Put it into .vimrc
:
let s:mons_en = ['Jan', 'Feb', 'Mar', 'Apr',
\ 'May', 'Jun', 'Jul', 'Aug',
\ 'Sep', 'Oct', 'Nov', 'Dec']
let s:months_en = ['January', 'February', 'March', 'April',
\ 'May', 'June', 'July', 'August',
\ 'September', 'October', 'November', 'December']
let s:months_ru = ['января', 'февраля', 'марта', 'апреля',
\ 'мая', 'июня', 'июля', 'августа',
\ 'сентября', 'октября', 'ноября', 'декабря']
let s:months = extend(s:months_en, s:months_ru)
let s:months = extend(s:months, s:mons_en)
"" * ISO-8601 2020-03-21
"" * RU 21 марта 2020
"" * EN 10 December 2012
"" * EN December 10, 2012
"" * EN 10 Dec 2012
"" * EN Dec 10, 2012
func! s:date_textobj(inner)
let save_cursor = getcurpos()
let cword = expand("<cword>")
if cword =~ '\d\{4}'
let rx = '^\|'
let rx = '\%(\D\d\{1,2}\s\+\%(' . join(s:months, '\|') . '\)\)'
let rx .= '\|'
let rx .= '\%(\s*\%(' . join(s:months, '\|') . '\)\s\+\d\{1,2},\)'
if !search(rx, 'bcW', line('.'))
call search('\s*\D', 'bcW', line('.'))
endif
elseif cword =~ join(s:months, '\|')
call search('^\|\D\ze\d\{1,2}\s\+', 'bceW')
elseif cword =~ '\d\{1,2}'
if !search('^\|\S\ze\%(' . join(s:months, '\|') . '\)\s\+\d\{1,2}', 'bceW')
call search('^\|[^0-9\-]', 'becW')
endif
endif
let rxdate = '\%(\d\{4}-\d\{2}-\d\{2}\)'
let rxdate .= '\|'
let rxdate .= '\%(\d\{1,2}\s\+\%(' . join(s:months, '\|') . '\)\s\+\d\{4}\)'
let rxdate .= '\|'
let rxdate .= '\%(\%(' . join(s:months, '\|') . '\)\s\+\d\{1,2},\s\+\d\{4}\)'
if !a:inner
let rxdate = '\s*\%('.rxdate.'\)\s*'
endif
if search(rxdate, 'cW')
normal v
call search(rxdate, 'ecW')
return
endif
call setpos('.', save_cursor)
endfunc
xnoremap <silent> id :<C-u>call <sid>date_textobj(1)<CR>
onoremap id :<C-u>normal vid<CR>
xnoremap <silent> ad :<C-u>call <sid>date_textobj(0)<CR>
onoremap ad :<C-u>normal vad<CR>
Put it into .vim/after/ftplugin/markdown.vim
:
"" Markdown header text object
" * inner object is the text between prev section header(excluded) and the next
" section of the same level(excluded) or end of file.
" * an object is the text between prev section header(included) and the next section of the same
" level(excluded) or end of file.
func! s:header_textobj(inner) abort
let lnum_start = search('^#\+\s\+[^[:space:]=]', "ncbW")
if lnum_start
let lvlheader = matchstr(getline(lnum_start), '^#\+')
let lnum_end = search('^#\{1,'..len(lvlheader)..'}\s', "nW")
if !lnum_end
let lnum_end = search('\%$', 'cnW')
else
let lnum_end -= 1
endif
if a:inner && getline(lnum_start + 1) !~ '^#\+\s\+[^[:space:]=]'
let lnum_start += 1
endif
exe lnum_end
normal! V
exe lnum_start
endif
endfunc
onoremap <buffer><silent> ih :<C-u>call <sid>header_textobj(v:true)<CR>
onoremap <buffer><silent> ah :<C-u>call <sid>header_textobj(v:false)<CR>
xnoremap <buffer><silent> ih :<C-u>call <sid>header_textobj(v:true)<CR>
xnoremap <buffer><silent> ah :<C-u>call <sid>header_textobj(v:false)<CR>
Put it into your .vimrc
:
"" Indent text object
"" Useful for python-like indentation based programming lanugages
func! s:indent_textobj(inner)
if getline('.') =~ '^\s*$'
let ln_start = s:detect_nearest_line()
let ln_end = ln_start
else
let ln_start = line('.')
let ln_end = ln_start
endif
let indent = indent(ln_start)
if indent > 0
while indent(ln_start) >= indent && ln_start > 0
let ln_start = prevnonblank(ln_start-1)
endwhile
while indent(ln_end) >= indent && ln_end <= line('$')
let ln_end = s:nextnonblank(ln_end+1)
endwhile
else
while indent(ln_start) == 0 && ln_start > 0 && getline(ln_start) !~ '^\s*$'
let ln_start -= 1
endwhile
while indent(ln_start) > 0 && ln_start > 0
let ln_start = prevnonblank(ln_start-1)
endwhile
while indent(ln_start) == 0 && ln_start > 0 && getline(ln_start) !~ '^\s*$'
let ln_start -= 1
endwhile
while indent(ln_end) == 0 && ln_end <= line('$') && getline(ln_end) !~ '^\s*$'
let ln_end += 1
endwhile
while indent(ln_end) > 0 && ln_end <= line('$')
let ln_end = s:nextnonblank(ln_end+1)
endwhile
endif
if a:inner || indent == 0
let ln_start = s:nextnonblank(ln_start+1)
endif
if a:inner
let ln_end = prevnonblank(ln_end-1)
else
let ln_end = ln_end-1
endif
if ln_end < ln_start
let ln_end = ln_start
endif
exe ln_end
normal! V
exe ln_start
endfunc
func! s:nextnonblank(lnum) abort
let res = nextnonblank(a:lnum)
if res == 0
let res = line('$')+1
endif
return res
endfunc
func! s:detect_nearest_line() abort
let lnum = line('.')
let nline = s:nextnonblank(lnum)
let pline = prevnonblank(lnum)
if abs(nline - lnum) > abs(pline - lnum) || getline(nline) =~ '^\s*$'
return pline
else
return nline
endif
endfunc
onoremap <silent>ii :<C-u>call <sid>indent_textobj(v:true)<CR>
onoremap <silent>ai :<C-u>call <sid>indent_textobj(v:false)<CR>
xnoremap <silent>ii :<C-u>call <sid>indent_textobj(v:true)<CR>
xnoremap <silent>ai :<C-u>call <sid>indent_textobj(v:false)<CR>
Related: