I have this function in my vimrc:
function! MyFunc(fl)
:!cat fl
" :!cat a:fl
" :!cat &fl
endfunction
command! -nargs=1 RunFunc :call MyFunc(<f-args>)
The problem is when I run :RunFunc ~/scripts/0-test in vim command, I get the error:
cat: f: No such file or directory
shell returned 1
I have looked at various websites like this, this, this, this and this, but none worked for me.
First, you don't need that colon in a scripting context:
function! MyFunc(fl)
!cat fl
endfunction
command! -nargs=1 RunFunc :call MyFunc(<f-args>)
Second, you can't pass an expressions like that. You need to concatenate the whole thing with :help :execute:
function! MyFunc(fl)
execute "!cat " .. fl
endfunction
command! -nargs=1 RunFunc :call MyFunc(<f-args>)
Third, function arguments are typed with a::
function! MyFunc(fl)
execute "!cat " .. a:fl
endfunction
command! -nargs=1 RunFunc :call MyFunc(<f-args>)
As for websites… they are useless. Vim comes with an exhaustive documentation that should be your first hit when stumbling on something and it just so happens that the user manual—which is mandatory reading—has a whole chapter on writing vimscript: :help usr_41.txt.
Related
I want to configure my Ruby fixer to perform the following sequence:
Turn syntax off
Run the rubocop fixer
Turn syntax on
According to :help ale-fix-configuration:
Synchronous functions and asynchronous jobs will be run in a sequence
for fixing files, and can be combined. For example:
let g:ale_fixers = {
\ 'javascript': [
\ 'DoSomething',
\ 'eslint',
\ {buffer, lines -> filter(lines, 'v:val !=~ ''^\s*//''')},
\ ],
\}
I tried to follow the example:
function! SyntaxTurnOff()
exec "syntax off"
endfunction
function! SyntaxTurnOn()
exec "syntax on"
endfunction
" FIXERS
let g:ale_fixers = {
\ '*': ['remove_trailing_lines', 'trim_whitespace'],
\ 'ruby': [
\ 'SyntaxTurnOff',
\ 'rubocop',
\ 'SyntaxTurnOn',
\],
\ 'python': ['flake8'],
\ 'json': ['jq'],
\}
However, when I try to execute it by calling :ALEFix in the editor, I get the following error:
Error detected while processing function ale#fix#Fix[37]..<SNR>305_RunFixer:
line 17:
E118: Too many arguments for function: SyntaxTurnOff
What am I doing wrong?
I found another way to make this work.
Rather than trying to sequence function calls within the fixers Object, I used autogroups instead.
First I defined the following functions:
function! SyntaxTurnOff()
"Turns syntax off only in current buffer
exec "syntax clear"
endfunction
function! SyntaxTurnOn()
exec "syntax on"
endfunction
Then, I used the built-in ALEFixPre and ALEFixPost autocommands:
augroup YourGroup
autocmd!
autocmd User ALEFixPre call SyntaxTurnOff()
autocmd User ALEFixPost call SyntaxTurnOn()
augroup END
My fixers are back to their previous, simple configuration.
" FIXERS
let g:ale_fixers = {
\ '*': ['remove_trailing_lines', 'trim_whitespace'],
\ 'ruby': ['rubocop'],
\ 'python': ['flake8'],
\ 'json': ['jq'],
\}
I'd be happy to hear of a better way, but this works for me, and I hope it helps someone else.
This came about because I had a 400-line file that was incredibly slow to fix, not because of rubocop, but because of syntax highlighting in Neovim. Before, running ALEFix would hold up that buffer for ages; now it's not instantaneous but it's pretty fast. To be fair, it's not due to ALEFix as such but rather to whatever Neovim has to do to redraw the buffer with syntax highlighting.
yesterday I got a very easy task, but unfortunatelly looks like i can't do with a nice code.
The task briefly: I have a lot of parameters, that I want to ask with whiptail "interactive" mode in the installer script.
The detail of code:
#!/bin/bash
address="192.168.0.1" # default address, what the user can modify
addressT="" # temporary variable, that I want to check and modify, thats why I don't modify in the function the original variable
port="1234"
portT=""
... #there is a lot of other variable that I need for the installer
function parameter_set {
$1=$(whiptail --title "Installer" --inputbox "$2" 12 60 "$3" 3>&1 1>&2 2>&3) # thats the line 38
}
parameter_set "addressT" "Please enter IP address!" "$address"
parameter_set "portT" "Please enter PORT!" "$port"
But i got the following error:
"./install.sh: line: 38: address=127.0.0.1: command not found"
If I modify the variable to another (not a parameter of function), works well.
function parameter_set {
foobar=$(whiptail --title "Installer" --inputbox "$2" 12 60 "$3" 3>&1 1>&2 2>&3)
echo $foobar
}
I try to use global retval variable, and assign to outside of the function to the original variable, it works, but I think it's not the nicest solution for this task.
Could anybody help me, what I do it wrong? :)
Thanks in advance (and sorry for my bad english..),
Attila
It seems that your whiptail command is not producing anyoutput because of the redirections. So the command substitution leaves the value empty. Try removing them. Also it's better to save the new value to a local variable first:
parameter_set() {
local NAME=$1
local NEWVALUE=$(whiptail --title "Installer" --inputbox "$2" 12 60 "$3")
export $NAME="$NEWVALUE"
}
Test CMakeLists.txt:
function(foo param)
return("hello")
endfunction()
message(foo("oops"))
When "cmake ." is run with the above file, it prints "foo(oops)". I expected it to print "hello".
How can I make one function receive the result of another in CMake?
CMake functions don't "return values" in the way the code example you gave thinks they do. In general, if a CMake builtin or function wants to return a value, it needs to take the name of a variable to store the result in:
function(foo param ret)
set(${ret} "hello ${param}" PARENT_SCOPE)
endfunction()
Then, you need to construct the control flow in the caller yourself:
foo("world" hello_world)
message(STATUS "foo returned: ${hello_world}")
foo(${hello_world} hello2)
message(STATUS "foo second call returned: ${hello2}")
Please have a look to the below vim function which I written in my /.gvimrc file.
The function id for deleting the "n" number of last characters in each line from the range of lines specified by "start_line" and "end_line".
function RLNC (n, start_line, end_line)
execute . a:start_line . "," . a:end_line . "s/.\{" . a:n . "}$//"
endfunction
but when I make the same as a function and call it in the vim
:call RLNC(3, 128, 203)
This is the actual operation I am doing here
:start_line,end_lines/.\{n}$//
This is nothing but
:128,203s/.\{3}$//
Please help me to find what is going wrong..?
its is giving errors
The error is:
E15: Invalid expression: . a:start_line . "," . a:end_line . "s/.\{" . a:n . "}$//"
So, the first period is suspect. The :execute command takes (one or multiple) expressions. String concatenation via . is only done between strings, not at the beginning.
Just leave off the first .:
execute a:start_line . "," . a:end_line . "s/.\{" . a:n . "}$//"
The manual concatenation is tedious. Better use printf():
execute printf("%d,%ds/.\{%d}$//", a:start_line, a:end_line, a:n)
The next problem is that inside double quotes, the backslash must be escaped (doubled). Better use single quotes:
execute printf('%d,%ds/.\{%d}$//', a:start_line, a:end_line, a:n)
Finally, Vim has a special syntax to pass a range to a function. See :help function-range-example. You do not need to use this, but it makes the invocation more natural:
:128,203call RLNC(3)
However, I would probably go ahead and define a custom command wrapping the function.
:command! -range -nargs=1 RLNC call RLNC(<args>, <line1>, <line2>)
If your function isn't actually more complex, we can now inline this and get rid of the function altogether:
:command! -range -nargs=1 RLNC execute printf('%d,%ds/.\{%d}$//', <line1>, <line2>, <args>)
(Note that without a function, the last search pattern gets clobbered.)
Thank for your reply, I am new to vim function and all. So I don't know much about the ":command!" and all. So I put it as function in the /.gvimrc file like below :
function RLNC (start_line, end_line, n)
if (a:start_line <= a:end_line)
execute printf(':%d,%ds/.\{%d}$//', a:start_line, a:end_line, a:n)
else
execute printf('Start line %d is more than End line %d ', a:start_line, a:end_line)
endif
endfunction
and its working fine when I use the :call RLNC(128, 203, 3) in my gvim files.
Thanks You
I'm having serious biggies trying to figure out how to evaluate an expression in a If statement using Tcl. This is what I have:
#!/bin/sh
#The next line executes wish - wherever it is \
exec wish "$0" "$#"
set apid "/var/run/apache2.pid"
set apsta [file exist $apid]
if { $apsta == 1 }
{
set result ":)"
}
else
{
set result ":("
}
label .status -text $result
pack .status
and this is what I get from the terminal:
# wan27
Error in startup script: wrong # args: no script following " $apsta == 1 " argument
while executing
"if { $apsta == 1 }"
(file "/usr/bin/wan27" line 9)
I'm just trying to output a happy smiley if Apache is running, a sad one if Apache is stopped - based upon the boolean condition whether or not the file "/var/run/apache2.pid" exists ...
The syntax of a Tcl if statement is
if condition statement else statement
which must be on one line. Braces allow continuation across lines and their placement is mandatory:
if { $apsta == 1 } {
set result ":)"
} else {
set result ":("
}
As you have it written, Tcl sees
if { $apsta == 1 }
and stops there yielding a syntax error.
MSW have already given you the correct answer but I think a little bit more explanation is needed to clear up some other confusions you are having based on your comments.
I will first explain things using non-tcl terminology since I think it is less confusing that way.
In tcl, if is not a statement. if is a function. That is the reason why the opening brace need to be on the same line: because a newline terminates the list of arguments to a function. For example, in the following code:
a b c d
e f
the Tcl interpreter will see two function calls. The first to function a with arguments b, c and d and the second to function e with a single argumrnt f. Similarly, in the following:
if a
b
Tcl sees a call to the function if with a single argument. Since if expects at least two arguments it (not the interpreter itself) throws an error complaining about wrong number of arguments.
This also explains why there must be a space between if and its first argument. It's just because in tcl names of variables and functions are literally allowed to contain almost anything including spaces, commas and non-printing characters like NUL. For example, you can define a function called a{b}:
proc a{b} {} {puts HA!}
a{b} ;# <-- prints out HA!
So if you do something like:
if{x} {y}
tcl will complain that the function if{x} is not defined.
if is not the only thing that works like this. Tcl doesn't really have keywords, just a standard library of built-in functions like for, foreach and while. The same rules apply to all of them.
not really important:
On a side, the if function in tcl works like the ternary operator in C: it returns a value. In fact you can do the following:
# It is unfortunate that this "give" function is not built in.
# We use it to return something from if without actually
# calling return:
proc give {x} {return $x}
set something [if {$x} {give "Very true indeed."} {give "Unfortunately false."}]