Плагин Vim для отображения текущей подпрограммы Perl - PullRequest
2 голосов
/ 12 февраля 2011

Я пытаюсь создать плагин Vim, который разделит окно под нагрузкой и имитирует информационную панель в верхней части моего терминала.У меня это работает, но я думаю, что я либо достиг предела своих знаний о синтаксисе Vim, либо в моем коде есть логическая проблема.

Желаемый эффект - обратный поиск любого объявленияиз подпрограммы Perl сформируйте мое текущее местоположение в активном буфере и отобразите строку в верхнем буфере.Я также пытаюсь заставить его пропустить этот буфер, когда я переключаю буферы с помощью Ctrl - R .Моя попытка сделать это до сих пор видна в путанице вложенных операторов if.

В любом случае, вот код .Я был бы очень признателен за любые отзывы.

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()

Аналогично вопросу VIM: отображение пользовательской панели ссылок в верхней части окна и вики-страницы Vim Tips Отображение имени текущей функциив программах на С .

1 Ответ

1 голос
/ 14 февраля 2011

После просмотра кода на http://blogs.perl.org/users/ovid/2011/01/show-perl-subname-in-vim-statusline.html, предложенного @Prakash, я решил поделиться своими улучшениями в скрипте.

Я немного поигрался с кодом одного его сайта и сделал улучшение. Это отобразит 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...