Is there a good place in .vim folder to store text filters? - perl

I would like to create a filter folder, best inside .vim and be able to run a text filter just with one file name:! filter.pl
I put up a Perl text filter to change all special Characters in a LaTeX Math Formula, which is running fine so far - only problem it is running on the whole line not the selected formula, but I can live with it ...
#!/usr/bin/perl -np
use strict;
use warnings;
# this filter transforms all special characters in Mathformular for LaTeX
s/\\/\\backslash /g;
s/([\$\#&%_{}])/\\$1/g;
But to call this filter is cumbersome
: '<,'>!"/Users/username/Library/Mobile Documents/com~apple~CloudDocs/my_vim_cheat_sheet/perl_filter.pl"
Apple put in the path to the iCloud a white space, so I have to put "" around! Where I put a collection of text filters?
Thank you for your answers
marek

You can safely create a subfolder with any name different from ones Vim uses itself (see :h 'rtp'). So this is ok:
:*!$HOME/.vim/filters/perl_filter.pl
Also Vim has a predefined interface for a general purpose filter called 'equalprg'. To make use of it simply set a global-local (i.e. both set and setlocal are meaningful) option equalprg to a fully qualified name of your script. Then hit = in visual mode to apply filter (or ={motion} in normal mode). (Read :h 'equalprg' :h =).
If you need several filters at once, and switching equalprg is not convenient, you can still try different options to reduce typing.
For example, mappings, such as
vnoremap <Leader>f :!/path/to/my/filter<CR>
Then hitting \f (or whatever is your "leader" key set) in the visual mode will result in the executing :'<,'>!/path/to/my/filter (note that the visual selection will be applied automatically).
Another attempt is to set a dedicated environment variable (which will be inherited by all child processes including shell(s). For example,
:let $filters = '~/.vim/filters'
:*!$filters/myfilter.pl
Of course, you can put those set equalprg=... vnoremap ... let $filters=... etc.etc. in your vimrc.

I would like to create a filter folder, best inside .vim and be able to run a text filter just with one file name :! filter.pl
Simply add the script to somewhere within your $PATH. Or, if you really only intend to use that from within Vim, then add that directory to your $PATH in your .vimrc, so you have it available there.
For example, if you'd like to use ~/.vim/scripts for your external Perl or shell scripts, you can use this in your ~/.vimrc:
call setenv('PATH', expand('~/.vim/scripts').':'.$PATH)
After that, you can simply use :'<,'> !filter.pl to run it. And Tab completion will work with the name of the script, type :!fil<Tab> and Vim will complete it to filter.pl, assuming it's a unique prefix.
The snippet above for your .vimrc has one minor issue, that if you :source your .vimrc during Vim runtime, it will keep adding the entry to $PATH multiple times. That doesn't typically break anything, only the entry will become longer, you might run into variable length issues.
You can fix it by checking whether that's present in path or not before updating it, perhaps with something like:
let scripts_dir = expand('~/.vim/scripts')
if index(split($PATH, ':'), scripts_dir) < 0
call setenv('PATH', scripts_dir.':'.$PATH)
endif
But also, about this:
I put up a Perl text filter to change all special Characters in a LaTeX Math Formula
s/\\/\\backslash /g;
s/([\$\#&%_{}])/\\$1/g;
Consider writing that in Vim instead.
In fact, almost the same syntax will work as a Vim function:
function! EscapeLatexMathFormula()
s/\\/\\backslash /eg
s/\([$#&%_{}]\)/\\\1/eg
endfunction
You can call it on a range, with:
:'<,'>call EscapeLatexMathFormula()
Calling it without a range will affect the current line only.
You can also make it into a command, with:
command! -range EscapeLatexMathFormula <line1>,<line2> call EscapeLatexMathFormula()
In which case you can simply use:
:'<,'>EscapeLatexMathFormula
You can use tab-completion for the function and command names (though, of course, you can pick shorter names if you'd like, as well.)
Note that user-defined command names need to start with an uppercase letter. Function names can start with an uppercase letter too (there are more options for function names, but making this global with an uppercase is probably the easiest here.)

Related

How to hard-wrap lines in VS Code at a specific character (NOT word wrap)

I have a Base64 encoded string in a text file that is one line. In other words it contains no line breaks. I want to insert a line break every 78 characters.
None of the "wrap" extensions I have found do this, since they're geared for word wrapping and use word boundaries. Running any of these functions does nothing since the string contains no spaces or word boundaries.
I can do it on Unix using something like fold -w 78 but this seems like something that should exist in VS Code or at least an extension.
I'm not aware of an extension that does specifically what you're asking for, but what I would do is use the Edit with Shell Command extension, and use it to run fold -w 78 on the text in question from within VSCode. The extension even has a "quick command" feature you can use to save that command for quick use if it is something you do often.
I use that extension fairly often for one-off transformations with things like sort, sed, tr, and fmt. It's really handy when you know how to express the desired transformation as a shell command.

Only autocomplete on an exact match in Sublime Text 2

I'm making a custom .tmLanguage file to highlight the syntax I'm using correctly and generally make coding with it easier. I'm almost done, and I got the autocompletion working using a .sublime-completions file.
There's just one minor flaw I'd like to change. I have a pretty long list of functions, and almost all of them contain an abbreviation of the word 'parameter', PAR. When I start typing that word, the following are all in the list of completions:
PAR command
DEFPAR command
JDATA command (because the description contains PAR)
SPAA command (because there's a P in the command and an A and an R in the description)
What I want is only for the commands that begin with PAR to show up, so from the list above, only the first item.
So, like this:
In other words, I want the completions to show up based on the literal string I'm typing, and only from the trigger part of my completions file, before the \t only.
That completions file looks like this:
Highlighted in orange is what I want my completions list to be based on.
I hope this is understandable. Any help is greatly appreciated.
This is not possible. By design Sublime's autocomplete feature uses fuzzy matching, so if there are a number of options that all contain the same pattern, but you don't quite remember which one you want, you can type the pattern and have all of the options available. The more you type, the smaller the list of possible options becomes. This is a good thingĀ®, otherwise you'd have to remember the exact command you're looking for, which kind of defeats the purpose of autocomplete and code hinting.

VIM as a full-featured extensible IDE for any language

Hello I would like to master VIM as my primary IDE. I know there are many plugins etc. but I have one question: Is possible for VIM to understand the particular language (in case I wont plugin for my language) in which code is written? I mean some rules that I can define and then use e.g. for auto-completion, refactoring, folding etc. For example consider following two perl codes in which I want refactor variables. In first example there are variables with same names but one is scalar and another are array and hash, in second example same name of variable as was defined before was used in another scope (loop etc.). Thus refactoring using simple text matching is not elegant way I thing:
1st example:
my #same_name;
my $same_name; # How to refactor this variable without affecting all other variables?
my %same_name;
$same_name[0] = 5;
$same_name{"key"} = 5;
$same_name = 5;
2nd example:
my #array;
my $already_existing_variable; # How to refactor this variable
foreach my $already_existing_variable (#array){
print $already_existing_variable; # Without affecting this variable
}
print $already_existing_variable; # Variable that should be also refactorized
Or how can I achieve that when I type $arr {and hit TAB here} it will automatically extend to $array[ ? For this VIM must to know that when I prepend $ before variable which was declared with # I want to access array elements.
Another example would be: how to fold code using e.g. BEGIN and END keywords? Those was jut trivial examples but I think you get the point. I think it is similar task to write own compiler or something. Thank you.
I'm using vim with my perl scripts almost all days:
Rename variables
App::EditorTools gives you the function to rename variables like Padre.
install App::EditorTool $ cpanm App::EditorTools
install vim plugin $ editortools install-vim
move cursor on the variable name in vim.
type \pL
I'm not sure why it parses wrong scope in the 2nd example, but you can temporarily wrap the foreach brock with lambda and rename variables inside the code block first.
sub {
foreach my $already_existing_variable (#array){
print $already_existing_variable; # Without affecting this variable
}
}->();
Reformat script indent
Perl::Tidy has perltidy command line tool to format your script.
install Perl::Tidy $ cpanm Perl::Tidy
create ~/.perltidyrc according to your taste. like folowing:
-pbp
-pt=2
-sbt=2
-bt=2
-bbt=2
-ce
-nbbc
set equalprg to perltidy in your ~/.vimrc
au FileType perl setl ep=perltidy
type gg=G in your script.
Syntax Check
vim's built-in compiler plugin for perl does very well.
set :compilerto perl in your ~/.vimrc
au FileType perl :compiler perl
type :make in normal mode
type :copen to open up quickfix window
if you don't want warnings in your quickfix list, you can unset the flag for it.
let g:perl_compiler_force_warnings = 0
$PERL5LIB is also important while invoking :make, you can give specific directories in it.
let &l:path = './lib,./blib/lib,./blib/arch,' . &l:path
let $PERL5LIB = substitute(&l:path, ',', ':', 'g')
Completions
vim has nice completion tool out of the box. see :help comple-generic
type $ar in insert mode and press CTRL-N
You might be interested in ctags too.
I can already tell something is wrong when the first sentence is "Hello I would like to master VIM as my primary IDE."
Vim is not an IDE. Vim is a text editor. (You can use google to find out more)
If you feel that the features an IDE provides (refactoring, smarter auto-completion...) are more important than the features that vim provides (fast movement, never take your hands off the home row, programmable editor...) then you should use an IDE, or an IDE with a vim plugin. Usually, if you want to mix IDE features with vim features, you do it with a plugin to the IDE, not the other way around (there are some exceptions such as eclim).

How can I use a simpler link syntax in org-mode?

I'd like to have links with the syntax [[foo bar]] go to files with the name foo bar.org. This would make using org-mode much more like using a personal local wiki.
Is this possible without breaking existing link functionality? I'd also ideally still be able to export to html, etc. with standard org-mode tools.
The best I've been able to do is something like: (setq org-link-abbrev-alist '(("o" . "file:%s.org")))
This lets me use the syntax [[o:foo bar]], but that is more verbose, and looks distractingly ugly inline. For example: The quick brown o:fox jumps over the o:lazy_dog. And [[o:foo bar][foo bar]] is even more verbose to type and edit (though it reads fine in org mode).
I don't have a ready made solution and am not a programmer, but this part is self-documenting in org.el, you can write a dedicated link search function. I cite:
"List of functions to execute a file search triggered by a link.
Functions added to this hook must accept a single argument, the search
string that was part of the file link, the part after the double
colon. The function must first check if it would like to handle this
search, for example by checking the `major-mode' or the file
extension. If it decides not to handle this search, it should just
return nil to give other functions a chance. If it does handle the
search, it must return a non-nil value to keep other functions from
trying.
Each function can access the current prefix argument through the
variable `current-prefix-arg'. Note that a single prefix is used to
force opening a link in Emacs, so it may be good to only use a numeric
or double prefix to guide the search function.
In case this is needed, a function in this hook can also restore the
window configuration before `org-open-at-point' was called using:
(set-window-configuration org-window-config-before-follow-link)")
See also Hyperlinks :: Custom Searches # gnu.org

avoiding exploit in perl variable extrapolation from file

I am optimizing a very time/memory consuming program by running it over a dataset and under multiple parameters. For each "run", I have a csv file, "setup.csv" set up with "runNumber","Command" for each run. I then import this into a perl script to read the command for the run number I would like, extrapolate the variables, then execute it on the system via the system command. Should I be worried about the potential for this to be exploited, (I am worried right now)? If so, what can I do to protect our server? My plan now is to change the file permissions of the "setup.csv" to read only and ownership to root, then go in as root whenever I need to append another run to the list.
Thank you very much for your time.
Run your code in taint mode with -T. That will force you to carefully launder your data. Only pass through strings that are ones you are expecting. Do not launder with .*, but rather check against a list of good strings.
Ideally, there a list of known acceptable values, and you validate against that.
Either way, you want to avoid the shell by using the multi-argument form of system or by using IPC::System::Simple's systemx.
If you can't avoid the shell, you must properly convert the text to pass to the command into shell literals.
Even then, you have to be careful of values that start with -. Lots of tools accept -- to denote the end options, allowing other values to be passed safely.
Finally, you might want to make sure the args don't contain the NUL character (\0).
systemx('tool', '--', #args)
Note: Passing arbitrary strings is not possible in Windows. Extra validation is required.