2011-02-11 2 views
2

로드시 창을 분할하고 터미널 상단의 정보 표시 줄을 시뮬레이트하는 Vim 플러그인을 만들려고합니다. 나는 일종의 일을 가지고 있지만 Vim 구문에 대한 지식이 한계에 다다 랐거나 코드에 논리 문제가 있다고 생각합니다.현재 Perl 서브 루틴을 표시하는 Vim 플러그인

원하는 효과는 현재 버퍼의 현재 위치에서 Perl 서브 루틴의 선언을 역 검색하여 최상위 버퍼에 표시하는 것입니다. 또한 버퍼를 전환 할 때 그 버퍼를 건너 뛰도록하려고합니다. Ctrl - . 내 시도는 지금까지 중첩 된 if 문을 엉망으로 만든 것으로 볼 수 있습니다.

어쨌든 여기에 the code입니다. 나는 누구 로부터든 의견을 크게 고맙게 생각한다. 질문 VIM: display custom reference bar on top of window와 빔 팁 위키 페이지 Show current function name in C programs 유사

let s:current_function_bufname = 'Current\ Function\/Subroutine' 
function! s:get_current_function_name(no_echo) 
    let lnum = line(".") 
    let col = col(".") 
    if a:no_echo 
     let s:current_function_name = getline(search("^[^s]*sub .*$", 'bW')) 
    else 
     echohl ModeMsg 
     echo getline(search("^[^s]*sub .*$", 'bW')) 
     "echo getline(search("^[^ \t#/]\\{2}.*[^:]\s*$", 'bW')) 
     echohl None 
    endif 
endfunction 

let s:previous_winbufnr = 1 
let s:current_function_name = '' 
let s:current_function_buffer_created = 0 
let s:current_function_bufnr = 2 
function! s:show_current_function() 
    let total_buffers = winnr('$') 
    let current_winbufnr = winnr() 
    if s:previous_winbufnr != current_winbufnr 
     if bufname(current_winbufnr) == s:current_function_bufname 
      if s:previous_winbufnr < current_winbufnr 
       let i = current_winbufnr + 1 
       if i > total_buffers 
        let i = 1 
       endif 
       if i == s:current_function_bufnr 
        let i = i + 1 
       endif 
       if i > total buffers 
        let i = 1 
       endif 
       exec i.'wincmd w' 
      else 
       let i = current_winbufnr - 1 
       if i < 1 
        let i = total_buffers 
       endif 
       if i == s:current_function_bufnr 
        let i = i - 1 
       endif 
       if i < 1 
        let i = total_buffers 
       endif 
       try 
        exec i.'wincmd w' 
       finally 
        exec total_buffers.'wincmd w' 
       endtry 
      endif 
     endif 
     let s:previous_winbufnr = current_winbufnr 
     return 1 
    endif 

    if s:current_function_buffer_created == 0 
     exec 'top 1 split '.s:current_function_bufname 
     call s:set_as_scratch_buffer() 
     let s:current_function_buffer_created = 1 
     let s:current_function_bufnr = winnr() 
    endif 

    call s:activate_buffer_by_name(s:current_function_bufname) 
    setlocal modifiable 

    call s:get_current_function_name(1) 
    call setline(1, s:current_function_name) 

    setlocal nomodifiable 
    call s:activate_buffer_by_name(bufname(current_winbufnr)) 
endfunction 

function! s:set_as_scratch_buffer() 
    setlocal noswapfile 
    setlocal nomodifiable 
    setlocal bufhidden=delete 
    setlocal buftype=nofile 
    setlocal nobuflisted 
    setlocal nonumber 
    setlocal nowrap 
    setlocal cursorline 
endfunction 

function! s:activate_buffer_by_name(name) 
    for i in range(1, winnr('$')) 
     let name = bufname(winbufnr(i)) 
     let full_name = fnamemodify(bufname(winbufnr(i)), ':p') 
     if name == a:name || full_name == a:name 
     exec i.'wincmd w' 
     return 1 
     endif 
    endfor 
    return 0 
endfunction 

set laststatus=2 
autocmd! CursorMoved,CursorMovedI,BufWinEnter * call s:show_current_function() 

.

+3

나는 정력 사용자가 아니에요, 그래서 코드에 대해 언급 할 수 없지만, 이것은 당신이 뭘 하려는지 관련이있을 수 있습니다 : http://blogs.perl.org/users/ovid/2011/01/show-perl-subname-in-vim-statusline.html –

+0

vim-perl 프로젝트에 관심이있을 수 있습니다. https : // github. com/vim-perl/vim-perl 여기에 Vim에 대한 Perl 지원이 계속된다. 이러한 개선 사항은 주요 vim 릴리즈로 되돌아갑니다. –

답변

1

@Prakash가 제안한 http://blogs.perl.org/users/ovid/2011/01/show-perl-subname-in-vim-statusline.html의 코드를 검토 한 후 스크립트에 개선점을 공유하기로 결정했습니다.

잠시 동안 자신의 사이트에서 코드 1로 연주하고 개선했습니다. 서브 루틴 밖에 있다면 N/A으로 표시됩니다. 하위 선언 들여 쓰기와 일치하지 않는 닫는 중괄호 들여 쓰기 기록이있는 경우 $indent 부분을 변경할 수 있습니다. 재미있어!

.vimrc :

syntax on 
setlocal laststatus=2 
setlocal statusline=\ %{HasPaste()}%F%m%r%h\ %w\ \ CWD:\ %r%{CurDir()}%h\ \ \ Position:\ %p%%\ %l/%L,%c 
if has("autocmd") 
    autocmd BufReadPost * if &syntax == 'perl' | source ~/.vim/perl_current_subroutine | endif 
endif 

.vim/perl_current_subroutine :

if ! exists("b:did_perl_statusline") && &syntax == 'perl' 
    setlocal statusline+=%(\ \ \ Subroutine:\ %{StatusLineIndexLine()}%) 
    let b:did_perl_statusline = 1 
endif 

if has('perl') 
perl << EOP 
    use strict; 
    sub current_perl_subroutine { 
     my $curwin = $main::curwin; 
     my $curbuf = $main::curbuf; 
     my $sub_name = 'N/A'; 

     #search up from cursor line to find a declaration of a subroutine 
     my $line_number = ($curwin->Cursor)[0]; 
     my $line = $curbuf->Get($line_number); 
     my $indent = ''; 
     if ($line !~ /^(\s*)sub\s+(\w+)\b/) { 
      $line = $curbuf->Get($line_number) while ($line_number-- > 0 && $line !~ /^(\s*)sub\s+(\w+)\b/); 
      ($indent, $sub_name) = ($1, $2); 
     } else { 
      $line_number--; 
      ($indent, $sub_name) = ($1, $2); 
     } 

     #if found, (try to) find the end of the subroutine 
     if ($sub_name ne 'N/A') { 
      my $end = $curbuf->Count(); 
      $line = $curbuf->Get($line_number); 
      if ($line !~ /}\s*$/) { 
       $line = $curbuf->Get($line_number) while ($line_number++ < $end && $line !~ /^($indent)?}\s*$/); 
       $line_number--; 
      } 
      $sub_name = 'N/A' if ($line =~ /^($indent)?}\s*$/ && ($curwin->Cursor)[0] > $line_number); 
     } 

     VIM::DoCommand("let current_perl_subroutine_name='$sub_name'"); 
    } 
EOP 

    function! StatusLineIndexLine() 
     perl current_perl_subroutine() 
     return current_perl_subroutine_name 
    endfunction 
endif