3 Stimmen

Vim-Plugin, um die aktuelle Perl-Unterprozedur anzuzeigen

Ich versuche, ein Vim-Plugin zu erstellen, das das Fenster beim Laden teilt und eine Infobalken am oberen Rand meines Terminals simuliert. Es funktioniert irgendwie, aber ich glaube, ich habe entweder die Grenzen meines Wissens über die Vim-Syntax erreicht oder es gibt ein Logikproblem in meinem Code.

Der gewünschte Effekt wäre, eine Rückwärtssuche nach einer Deklaration einer Perl-Unterfunktion ab meinem aktuellen Standort im aktiven Puffer durchzuführen und die Zeile im oberen Puffer anzuzeigen. Ich versuche auch, zu verhindern, dass dieser Puffer übersprungen wird, wenn ich Puffer mit Strg-R wechsle. Mein bisheriger Versuch dazu ist im Durcheinander von nested if-Anweisungen zu sehen.

Wie auch immer, hier ist der Code. Ich würde das Feedback von jedem sehr schätzen.

let s:current_function_bufname = 'Aktuelle\ Funktion\/Unterfunktion'
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()

Ähnlich der Frage VIM: eigene Referenzleiste oberhalb des Fensters anzeigen und der Vim-Tipps-Wikiseite Aktuellen Funktionsnamen in C-Programmen anzeigen.

3 Stimmen

Ich bin kein Vim-Benutzer, daher kann ich nichts zu deinem Code sagen, aber dies könnte im Zusammenhang damit stehen, was du zu tun versuchst: blogs.perl.org/users/ovid/2011/01/…

0 Stimmen

Du könntest am vim-perl Projekt interessiert sein: github.com/vim-perl/vim-perl Hier wird die gesamte Perl-Unterstützung für Vim entwickelt. Diese Verbesserungen werden dann in die Hauptveröffentlichungen von Vim integriert.

1voto

Andrew Sohn Punkte 635

Nachdem ich den Code auf http://blogs.perl.org/users/ovid/2011/01/show-perl-subname-in-vim-statusline.html überprüft hatte, der von @Prakash vorgeschlagen wurde, beschloss ich, meine Verbesserungen am Skript zu teilen.

Ich habe etwas mit dem Code auf seiner Seite gespielt und eine Verbesserung vorgenommen. Dies wird N/A anzeigen, wenn Sie sich außerhalb der Unterfunktion befinden. Wenn Sie eine Geschichte haben, in der Ihr Einrückungszeichen der schließenden Klammer nicht mit Ihrem Unterfunktionsdeklarationseinrücken übereinstimmt, möchten Sie möglicherweise den $indent Teil ändern. Viel Spaß!

.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+=%(\ \ \ Unterfunktion:\ %{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';

        # Suche von der Cursor-Zeile nach oben, um eine Deklaration einer Unterfunktion zu finden
        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);
        }

        # Wenn gefunden, versuchen Sie, das Ende der Unterfunktion zu finden
        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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X