Closed dbaelde closed 11 years ago
Acknowledged. I'll try and find vim-using contributors for this :)
I spent a while trying to remember the vim scripting I know... I did not remember anything. Best solution I have so far is this setlocal indentexpr=GetOCPIndent(v:lnum)
function GetOCPIndent(l) silent execute "1,".a:l."w !ocp-indent --numeric | tail -n 2 | head -n 1 > .ocpindentlevel" return system("cat .ocpindentlevel") endfunction
It sucks to go through a file, and it makes the screen flicker. The good solution seems to be :redir but I couldn't make it to work.
Note that I don't know the use of the former vim script you provided, for me the above is enough, although it is probably sub-optimal when indenting a region.
I started working on better integration of ocp-indent in vim. I submitted a pull request a few days ago to use ocp-indent interactively instead of spawning a new process each time, though I am not sure it is the way to go.
Here is the python helper I use in vim: ocpindent.py ocpindent.vim
Results are encouraging so far, but integration is far from perfect.
@dbaelde I don't know much about vim scripting, but if you could find a way to specify the --lines
option to ocp-indent, you could save the pipe through tail/head (and maybe the silent+redirect+cat ?) ; incidentally, that would get the indentation of the current line to adapt relatively to the lines above if they don't follow the expected indentation.
Maybe this is not well documented, but --lines
+ --numeric
only gives output for the concerned lines. So maybe something like:
function GetOCPIndent(l)
execute "w !ocp-indent --numeric --lines ".a:l
endfunction
could be enough ?
Louis, you're right, I should really have used lines. However this doesn't save the redirect dance: the problem is that execute seems to be the only way to get the file into a process' stdin, and system is the only way to get a process' stdout...
The future of vim scripting might be to use interfaces such as python (or lua, perl..). I haven't tested def-lkb's scripts but I'm hopeful that he has the right answer and is getting close.
On Tue, Apr 2, 2013 at 10:56 AM, Louis Gesbert notifications@github.comwrote:
@dbaelde https://github.com/dbaelde I don't know much about vim scripting, but if you could find a way to specify the --lines option to ocp-indent, you could save the pipe through tail/head (and maybe the silent+redirect+cat ?) ; incidentally, that would get the indentation of the current line to adapt relatively to the lines above if they don't follow the expected indentation.
Maybe this is not well documented, but --lines + --numeric only gives output for the concerned lines. So maybe something like:
function GetOCPIndent(l) execute "w !ocp-indent --numeric --lines ".a:l endfunction
could be enough ?
— Reply to this email directly or view it on GitHubhttps://github.com/OCamlPro/ocp-indent/issues/54#issuecomment-15763818 .
David
Just a message to tell you that I would be very interested if you make '==' work to indent a line in vim since the result of the indentation with 'ocp-indent' seems very nice. Unfortunately, I have no time at the moment to find a solution myself... sorry.
Two options:
Either set equalprg to '':
:set equalprg=
This way, vim will invoke ocp-indent for every line. This will be quite slow, especially considering "quadratic behavior" (ocp-indent will reparse everyline already indented for each new line…). I have an experimental vim plugin making use of the state checkpointing introduced in ocp-indent master that partially solve this problem.
Otherwise, you will have to workaround vim handling of "=". For instance using this snippet (put it in your .vimrc):
python <<END
import vim
def ocpindent_equal():
r = vim.current.range
w = vim.current.window
pos = w.cursor
vim.command("0,'>!%s --lines %d-" % ("ocp-indent", r.start+1))
w.cursor = pos
END
function! OcpIndentEqual()
py ocpindent_equal()
endfunction!
Then
call OcpIndentEqual()
instead of using "=" (for instance, mapping "=" to this statemant in normal and visual mode).
Thank you. I'll try that as soon as possible, but I don't understand the first suggestion. Do you really mean setting equalprg
to nothing ? or do you meant to ocp-indent
? (I already have setlocal equalprg=ocp-indent
in my .vimrc)
By setting equalprg to nothing, vim will fallback to indentexpr to compute line indentation. indentexpr is what is used to indent during edition (and ocp-indent.vim essentially plug ocp-indent binary to the indentexpr "api").
The pros is that you will get exactly the same behavior as reindenting line-by-line manually, the cons is that it will do an enormous amount of useless work (on big file, it will feel really slow).
The solution with an empty equalprg
is working great : thanks !
I don't like having big files anyway, and on the files that I tried, it doesn't feel slow at all.
Many thanks again.
I agree the current mode is not as featureful as the emacs plugin.
For the record, here is an updated version which:
The plugin filters the whole document and only indents the selected text with the --lines ocp-indent option. This is not an issue, even with large files (I've a 15k+ loc file which get indented almost instantly by this plugin).
One of the issue is that vim tends to jump to the beginning of the file when you undo the indendation, but this version is still better that the one shipped with ocp-indent.
" Assumes that ocp-indent is in PATH.
" This can be overriden by setting g:ocp_indent_binary in your .vimrc. Eg.
"
" let g:ocp_indent_binary = "/home/jo/bin/ocp-indent.exe"
"
function! PreserveExec(expr)
let l:pos = getpos(".")
let l:winview = winsaveview()
try
execute(a:expr)
finally
call setpos(".", l:pos)
call winrestview(l:winview)
endtry
endfunction
function! OcpIndentRange() range
let l:ocp_indent_binary = exists("g:ocp_indent_binary") ? g:ocp_indent_binary : "ocp-indent"
call PreserveExec(':%!' . l:ocp_indent_binary . ' -l ' . a:firstline . '-' . a:lastline)
endfunction
function! OcpIndentBuffer()
let l:ocp_indent_binary = exists("g:ocp_indent_binary") ? g:ocp_indent_binary : "ocp-indent"
call PreserveExec(':%!' . l:ocp_indent_binary)
endfunction
vnoremap <LocalLeader>i :call OcpIndentRange()<CR>
nnoremap <LocalLeader>i :call OcpIndentBuffer()<CR>
map == :call OcpIndentRange()<CR>
vnoremap = :call OcpIndentRange()<CR>
Sorry, I didn't have time to test it before... I have just copied that in my vim files, and it seems to work fine. Many thanks !
I'm closing this issue, hopeful that Jonathan's new script does the trick. Feel free to reopen, or open new issues for remaining vim-related limitations.
The current vim script does not use ocp-indent in a way that is really useful: it only filters one or several lines through the tool. As a result, indenting a single line usually does not result in the desired indentation, since the context is ignored.
Also, it seems that the --numeric option would be more lightweight than replacing parts of the buffer by ocp-indent's output.