Code-ART
view release on metacpan or search on metacpan
lib/Code/ART.pm view on Meta::CPAN
=over
=item *
The original source code (as a string),
=item *
A string index at which some usage of the variable is located
(i.e. a point in the source where a hypothetical cursor would be "over" the variable).
=item *
The new name of the variable.
=back
The subroutine returns a hash with a single entry:
{ source => $copy_of_source_string_with_the_variable_renamed }
lib/Code/ART.pm view on Meta::CPAN
{ failed => "reason_for_failure" }
=head2 Vim integration
The module distribution includes a Vim plugin: F<vim/perlart.vim>
This plugin sets up a series of mappings that refactor or rename
code elements that have been visually selected or on which the
cursor is sitting.
For example, the <CTRL-S> mapping yanks the visual selection, refactors the
code into a subroutine, requests a name for the new subroutine, requests
a return value (if one seems needed), and then pastes the resulting
subroutine call over the original selected text.
The mapping also places the resulting subroutine definition code in the
unnamed register, as well as in register C<"s> (for "B<s>ubroutine"),
so that the definition is easy to paste back into your source somewhere.
The following Normal mode mappings re also available:
=over
=item <CTRL-N>
Rename the variable under the cursor.
=item <CTRL-S>
Search for all instances of the variable under the cursor.
B<I<WARNING>>: In some environments, C<CTRL-S> will suspend terminal
interactions. If your terminal locks up when you use this mapping,
hit C<CTRL-Q> to restart terminal interactions. In this case,
you will need to either change the behaviour of C<CTRL-S> in
your terminal (for example:
L<https://coderwall.com/p/ltiqsq/disable-ctrl-s-and-ctrl-q-on-terminal>,
or L<https://stackoverflow.com/questions/3446320/in-vim-how-to-map-save-to-ctrl-s>),
or else change this mapping to something else.>
=item gd
Jump to the declaration of the variable under the cursor.
=item E<0x2a>
Jump to the next usage of the variable under the cursor.
=back
The following Visual mode mappings are also available:
=over
=item <CTRL-M>
Match all instances of the variable under the cursor.
=item <CTRL-H>
Hoist all instances of the visually selected code into a lexical variable.
=item <CTRL-C>
Hoist all instances of the visually selected code into a lexical closure.
=item <CTRL-R>
lib/Code/ART/API/Vim.pm view on Meta::CPAN
print _Perl_to_VimScript({
cacograms => join('\|', @cacograms),
undeclared_vars => join('\|', @undeclared_vars),
unused_vars => join('\|', @unused_vars),
});
}
my $VimOWS = '\%(\_s*\%(#.*\_s*\)*\)';
sub classify_var_at {
# Unpack the specified variable position (i.e. the byte number in the buffer)
my ($cursor_byte) = @_;
# Grab the source code, which will be sent through the input filestream...
my $source = do { local $/; readline(*ARGV); };
# Ask Code::ART to do the actual classification
# (making allowance for the fact that Vim byte numbers start at 1,
# but Perl string indexes start at zero)...
my $info = Code::ART::_classify_var_at($source, $cursor_byte - 1);
# Make sure the resulting information has valid 'sigil' entry...
$info->{sigil} //= q{};
# Convert the various locations found to Vim line/column coordinates...
$info->{matchloc} = _line_and_column_from_ID($source,
[$info->{declared_at}, keys %{$info->{used_at}}]);
$info->{declloc} = _line_and_column_from_ID($source, [$info->{declared_at}]);
# Convert scope details to Vim formats...
vim/perlart.vim view on Meta::CPAN
highlight default link PerlART_Parograms Normal
" How insufficiently descriptive variable names will be displayed...
highlight default link PerlART_Cacograms Normal
endfunction
" Available keymappings (change these to suit your own preferences)...
function! PerlART_API_setup () abort
" Rename the variable under the cursor...
silent nmap <silent><buffer><expr> <C-N> PerlART_RenameVariable()
" Search for all instances of the variable under the cursor...
silent nmap <silent><buffer><expr> <C-M> PerlART_MatchAllUses()
" Jump to the declaration of the variable under the cursor...
silent nmap <silent><buffer><expr> gd PerlART_GotoDefinition()
" Jump to the next instance of the variable under the cursor...
silent nmap <silent><buffer><special> * :silent call PerlART_GotoNextUse()<CR>
" In visual mode, hoist into a variable all instances of the variable under the cursor...
silent xnoremap <silent><buffer><expr> <C-H> PerlART_HoistExpr('all','variable')
" In visual mode, hoist into a closure all instances of the variable under the cursor...
silent xnoremap <silent><buffer><expr> <C-C> PerlART_HoistExpr('all','closure')
" In visual mode, hoist into a subroutine all instances of the variable under the cursor...
silent xnoremap <silent><buffer><expr> <C-R> PerlART_RefactorToSub('all')
" Doubling the trigger causes only the single instance under the cursor to be refactored...
silent xnoremap <silent><buffer><expr> <C-H><C-H> PerlART_HoistExpr('one','variable')
silent xnoremap <silent><buffer><expr> <C-C><C-C> PerlART_HoistExpr('one','closure')
silent xnoremap <silent><buffer><expr> <C-S><C-S> PerlART_RefactorToSub('one')
endfunction
" These happen automatically...
augroup PerlRefactor
autocmd!
autocmd FileType perl silent call PerlART_API_setup()
autocmd FileType perl silent call PerlART_SetHighlights()
vim/perlart.vim view on Meta::CPAN
"=======================================================================
" IMPLEMENTATION...
"=====[ Variable renaming ]=========
function! PerlART_VarRename () abort
call setpos("'r", getcurpos())
" Find the character offset of the desired (cursored) variable in the source code...
let var_offset = wordcount()['cursor_chars'] - 1
" Grab the entire source code from the buffer...
let src = join(getline(1,'$'), "\n")
" Get the full name of the variable under the cursor...
let cmd = printf("perl -MCode::ART -E'get_variable_for_Vim(%d)'", var_offset)
let var_name = substitute(system(cmd, src), '\n', '', 'g')
if var_name == ""
echohl WarningMsg
echo "Can't rename there (cursor is not over a variable)"
echohl NONE
return
endif
" Ask for the new name...
call inputsave()
echohl WarningMsg
let new_name = input('Rename ' . var_name . ' to: ' . var_name[0])
echohl NONE
call inputrestore()
vim/perlart.vim view on Meta::CPAN
\ 'for' : 'PerlART_Package'
\}
function! PerlART_RunVarAnalysis () abort
" Kill any incomplete analysis...
if has_key(b:,'PerlART_RVA_job')
call job_stop(b:PerlART_RVA_job)
endif
" Start a new analysis...
let code = 'classify_var_at('.wordcount()['cursor_chars'].');'
let b:PerlART_RVA_job
\ = job_start(['perl', '-MCode::ART::API::Vim', '-E', code],
\{"in_io" : "buffer", "in_name" : "%", "out_cb": "PerlART_HandleVarAnalysis"})
endfunction
let s:PerlART_MatchID_Decl = 664668
let s:PerlART_MatchID_Usage = 668664
let s:PerlART_MatchID_Homograms = 665667
let s:PerlART_MatchID_Parograms = 663668
let s:PerlART_MatchID_ScopeBar = 667665
vim/perlart.vim view on Meta::CPAN
if &foldexpr == 'FS_FoldSearchLevel()'
let @/ = b:PerlART_cursvar['matchloc'].b:PerlART_cursvar['matchname']
normal zx
endif
endfunc
function! PerlART_RenameVariable () abort
" Are we actually on a variable?
if has_key(b:PerlART_cursvar, 'failed')
echohl PerlART_Error
echo 'Please place the cursor over a variable and try again'
echohl NONE
return ''
endif
" What's the new name???
func! PerlART_rename_aliases (A,C,P)
return map(keys(get(b:PerlART_cursvar,'aliases',{})), {_,v -> strpart(v,1)})
endfunc
echohl PerlART_Message
let g:new_name = input('Rename '.b:PerlART_cursvar['decl_name'].' --> '.b:PerlART_cursvar['sigil'],
vim/perlart.vim view on Meta::CPAN
return ''
endif
endif
return ':%s/' . b:PerlART_cursvar['matchloc'].b:PerlART_cursvar['matchnameonly'] . '/\=g:new_name/g' . "\<CR>``"
endfunction
function! PerlART_GotoDefinition () abort
if has_key(b:PerlART_cursvar, 'failed')
echohl PerlART_Error
echo 'Please place the cursor over a variable and try again'
echohl NONE
return ""
elseif get(b:PerlART_cursvar, 'declared_at', -1) < 0
echohl PerlART_Error
echo 'This variable has no declaration in the current file'
echohl NONE
return ""
else
return '/'.b:PerlART_cursvar['declloc'].b:PerlART_cursvar['matchname']."\<CR>"
endif
( run in 0.261 second using v1.01-cache-2.11-cpan-4d50c553e7e )