Skip to content

Instantly share code, notes, and snippets.

@Tarmean
Last active August 19, 2019 21:57
Show Gist options
  • Save Tarmean/ccceb67463871102d7649344b814a8d1 to your computer and use it in GitHub Desktop.
Save Tarmean/ccceb67463871102d7649344b814a8d1 to your computer and use it in GitHub Desktop.
function! CsvHack#SetupScrolllock()
if (exists("b:csvhack_scrolllock_win"))
return
endif
let b:csvhack_scrolllock_win = v:true
setlocal scrollbind
setlocal scrollopt=hor
setlocal nowrap
split
wincmd k
let l:scrolllock_win = win_getid()
resize 1
norm! gg
wincmd j
let l:main_win = win_getid()
augroup Scrolllock
au!
exec "autocmd WinLeave,BufLeave <buffer> call CsvHack#CloseWin(" . l:scrolllock_win . ", ". l:main_win . ")"
augroup END
setlocal nostartofline
exec "nnoremap <buffer> <a-h> F" . b:seperator_char . "<esc>"
exec "nnoremap <buffer> <a-l> f" . b:seperator_char . "<esc>"
nnoremap <buffer> <a-j> <c-f>
nnoremap <buffer> <a-k> <c-b>
nmap <buffer> <space><space> :call CsvHack#ExpandScript()<cr>
endfunc
function! CsvHack#ClearUndo()
let l:old_undolevels = &undolevels
setlocal undolevels=-1
exe "normal a \<BS>\<Esc>"
exec "setlocal undolevels =" . l:old_undolevels
setlocal nomodified
endfunc
function! CsvHack#CloseWin(scrolllock_win, main_win)
if (!exists("b:csvhack_scrolllock_win"))
return
end
unlet b:csvhack_scrolllock_win
let [l:tab_num, l:win_num] = win_id2tabwin(a:scrolllock_win)
if (l:tab_num != 0 || l:win_num != 0)
exec l:tab_num . 'tabdo ' . l:win_num . "wincmd c"
endif
let [l:tab_num, l:win_num] = win_id2tabwin(a:main_win)
if (l:tab_num != 0 || l:win_num != 0)
exec l:tab_num . 'tabdo ' . l:win_num . "windo setlocal noscrollbind"
endif
endfunction
function! s:count_before(char, col, string)
let l:substr = strpart(a:string, 0, a:col)
return count(l:substr, a:char)
endfunction
function! s:regex_for_count(count, char)
let l:result = "\\v^("
let l:i = 0
let l:part = "[^" . a:char . "]*"
while (l:i < a:count)
let l:result = l:result . l:part . a:char
let l:i += 1
endwhile
let l:result = l:result . ")(" . l:part
let l:result = l:result . ")(" . a:char . ".*)?$"
return l:result
endfunction
function! CsvHack#ExpandScript()
if (!exists("b:seperator_char"))
throw "unknown seperator char"
endif
let l:old_buf = bufnr("%")
let l:lnum = line(".")
let l:cnum = col(".")
let l:old_line = getline(l:lnum)
let l:csv_col = s:count_before(b:seperator_char, l:cnum, l:old_line)
let l:pat = s:regex_for_count(l:csv_col, b:seperator_char)
let l:res = trim(substitute(l:old_line, l:pat, '\2', ''))
let l:is_func = s:is_column_function(l:old_buf, l:pat)
let l:callback = "call CsvHack#CompactScript(" . l:old_buf . "," . l:lnum . ",'" . l:pat . "', '" . b:seperator_char . "', ". l:is_func . ")"
if (len(l:res))
new
set buftype=acwrite
set bufhidden=wipe
call append(0, l:res)
if (l:is_func)
set ft=haxe
end
exec "autocmd BufWriteCmd <buffer> " . l:callback
nnoremap <buffer> <esc> :q<cr>
call CsvHack#Unescape(l:is_func)
call CsvHack#ClearUndo()
file Row Entry
endif
endfunc
function! s:flags()
if &gdefault
return ""
else
return "g"
endif
endfunction
function! CsvHack#Unescape(is_func)
if (a:is_func)
silent! %s/\v%(([{};])\s*)@>%(else)@!/\1\r
norm =ie
%g/^$/d
for [l:from, l:to] in g:CsvHack#ScriptEscapeChars
exec 'silent! %s/' . s:regex_escape(l:from) . '/' . l:to . '/' . s:flags()
endfor
else
for [l:from, l:to] in g:CsvHack#TextEscapeChars
exec 'silent! %s/' . s:regex_escape(l:from) . '/' . l:to . '/' . s:flags()
endfor
end
endfunction
let g:CsvHack#ScriptEscapeChars = [ ['~' , '"'], ['|' , ','], ['#' , '||']]
let g:CsvHack#TextEscapeChars = [ ['[;]' , ','], ['|' , "\r"] ]
function! s:is_column_function(buffer_id, regex)
let l:line = getbufline(a:buffer_id, 1)[0]
let l:part = substitute(l:line, a:regex, '\2', 'g')
return l:part =~# 'Script'
endfunction
function! s:regex_escape(char)
if (a:char == "\r")
return "\\M\n"
end
return '\M' . a:char
endfunction
function! CsvHack#Escape(is_func, lines, seperator_char)
if (a:is_func)
let l:buffer = trim(join(map(a:lines, "trim(v:val)"), " "))
for [l:k, l:v] in reverse(g:CsvHack#ScriptEscapeChars)
let l:buffer = substitute(l:buffer, s:regex_escape(l:v), l:k, 'g')
endfor
else
let l:buffer = join(map(a:lines, "trim(v:val)"), "\n")
if (len(l:buffer) == 0)
return ""
else
let l:buffer = l:buffer[0:-2]
end
for [l:k, l:v] in reverse(g:CsvHack#TextEscapeChars)
let l:buffer = substitute(l:buffer, s:regex_escape(l:v), l:k, 'g')
endfor
end
return l:buffer
endfunction
function! CsvHack#CompactScript(buf_nr, line, pat, seperator_char, is_func)
let l:lines = getline(1, '$')
let l:buffer = CsvHack#Escape(a:is_func, l:lines, a:seperator_char)
let l:old_line = getbufline(a:buf_nr, a:line)[0]
let l:prefix = substitute(l:old_line, a:pat, '\1', "")
let l:old_len = len(substitute(l:old_line, a:pat, '\2', ""))
let l:suffix = substitute(l:old_line, a:pat, '\3', "")
let l:buffer = ' ' . l:buffer . ' '
let l:buffer = substitute(l:buffer, '\s\+', ' ', 'g')
let l:buffer = l:buffer . repeat(' ', max([0, l:old_len - len(l:buffer)]))
call setbufline(a:buf_nr, a:line, l:prefix . l:buffer . l:suffix)
set nomodified
endfunction
augroup ScrolllockFile
au!
autocmd BufRead *.csv call CsvHack#TableModeAlign()
autocmd WinEnter,BufEnter *.csv call CsvHack#SetupScrolllock()
autocmd BufWriteCmd *.csv call CsvHack#HijackSaving()
augroup END
function! CsvHack#HijackSaving()
if (!exists("b:seperator_char"))
throw "unknown seperator char"
endif
let l:content = join(getline(1,'$'), "\n")
let l:normalized = substitute(l:content, '\v\s*' . b:seperator_char . ' ', b:seperator_char, 'g')
call writefile(split(l:normalized, '\n', 1), expand('%'), 'b')
set nomodified
return 1
endfunc
function! CsvHack#TableModeAlign()
let b:seperator_char = match(getline(1), ',') != -1 ? ',' : ';'
silent! %s/\v\|/§
silent! exec "%s/\\v".b:seperator_char."/|"
norm ggG0I| 
TableModeRealign
silent! exec "%s/\\v\\|/" . b:seperator_char
silent! exec "%s/\\v^" . b:seperator_char . " //"
silent! %s/§/|
endfunc
...
Plug 'dhruvasagar/vim-table-mode', { 'on': ['TableModeEnable', 'TableModeRealign'] }
...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment