Is there a way to do line break in AutoHotKey souce code? My code is getting longer than 80 characters and I would like to separate them neatly. I know we can do this in some other language, such as VBA for example below:
http://www.excelforum.com/excel-programming-vba-macros/564301-how-do-i-break-vba-code-into-two-or-more-lines.html
If Day(Date) > 10 _
And Hour(Time) > 20 Then _
MsgBox "It is after the tenth " & _
"and it is evening"
Is there a souce code line break in AutoHotKey? I use a older version of the AutoHotKey, ver 1.0.47.06
There is a Splitting a Long Line into a Series of Shorter Ones section in the documentation:
Long lines can be divided up into a collection of smaller ones to
improve readability and maintainability. This does not reduce the
script's execution speed because such lines are merged in memory the
moment the script launches.
Method #1: A line that starts with "and", "or", ||, &&, a comma, or a
period is automatically merged with the line directly above it (in
v1.0.46+, the same is true for all other expression operators except
++ and --). In the following example, the second line is appended to the first because it begins with a comma:
FileAppend, This is the text to append.`n ; A comment is allowed here.
, %A_ProgramFiles%\SomeApplication\LogFile.txt ; Comment.
Similarly, the following lines would get merged into a single line
because the last two start with "and" or "or":
if (Color = "Red" or Color = "Green" or Color = "Blue" ; Comment.
or Color = "Black" or Color = "Gray" or Color = "White") ; Comment.
and ProductIsAvailableInColor(Product, Color) ; Comment.
The ternary operator is also a good candidate:
ProductIsAvailable := (Color = "Red")
? false ; We don't have any red products, so don't bother calling the function.
: ProductIsAvailableInColor(Product, Color)
Although the indentation used in the examples above is optional, it might improve
clarity by indicating which lines belong to ones above them. Also, it
is not necessary to include extra spaces for lines starting with the
words "AND" and "OR"; the program does this automatically. Finally,
blank lines or comments may be added between or at the end of any of
the lines in the above examples.
Method #2: This method should be used to merge a large number of lines
or when the lines are not suitable for Method #1. Although this method
is especially useful for auto-replace hotstrings, it can also be used
with any command or expression. For example:
; EXAMPLE #1:
Var =
(
Line 1 of the text.
Line 2 of the text. By default, a line feed (`n) is present between lines.
)
; EXAMPLE #2:
FileAppend, ; The comma is required in this case.
(
A line of text.
By default, the hard carriage return (Enter) between the previous line and this one will be written to the file as a linefeed (`n).
By default, the tab to the left of this line will also be written to the file (the same is true for spaces).
By default, variable references such as %Var% are resolved to the variable's contents.
), C:\My File.txt
In the examples above, a series of lines is bounded at
the top and bottom by a pair of parentheses. This is known as a
continuation section. Notice that the bottom line contains
FileAppend's last parameter after the closing parenthesis. This
practice is optional; it is done in cases like this so that the comma
will be seen as a parameter-delimiter rather than a literal comma.
Please read the documentation link for more details.
So your example can be rewritten as the following:
If Day(Date) > 10
And Hour(Time) > 20 Then
MsgBox
(
It is after the tenth
and it is evening
)
I'm not aware of a general way of doing this, but it seems you can break a line and start the remainder of the broken line (e.g. the next real line) with an operator. As long as the second line (and the third, fourth, etc., as applicable) starts with (optional whitespace plus) an operator, AHK will treat the whole thing as one line.
For instance:
hello := "Hello, "
. "world!"
MsgBox %hello%
The presence of the concatenation operator . at the logical beginning of the second line here makes AHK treat both lines as one.
(I also tried leaving the operator and the end of the first line and starting the second off with a double-quoted string; that didn't work.)
Related
I am trying to parse the text output of a shell command using txr.
The text output uses a tab indented line following it to continue the current line (not literal \t characters as I show below). Note that on other variable assignment lines (that don't represent extended length values), there are leading spaces in the input.
Variable Group: 1
variable = the value of the variable
long_variable = the value of the long variable
\tspans across multiple lines
really_long_variable = this variable extends
\tacross more than two lines, but it
\tis unclear how many lines it will end up extending
\tacross ahead of time
Variable Group: 2
variable = the value of the variable in group 2
long_variable = this variable might not be that long
really_long_variable = neither might this one!
How might I capture these using the txr pattern language? I know about the #(freeform) directive and it's optional numeric argument to treat the next n lines as one big line. Thus, it seems to me the right approach would be something like:
#(collect)
Variable Group: #i
variable = #value
#(freeform 2)
long_variable = #long_value
#(set long_value #(regsub #/[\t ]+/ "" long_value))
#(freeform (count-next-lines-starting-with-tab))
really_long_variable = #really_long_value
#(set really_long_value #(regsub #/[\t ]+/ "" really_long_value))
#(end)
However, it's not clear to me how I might write the count-next-lines-starting-with-tab procedure with TXR lisp. On the other hand, maybe there is another better way I could approach this problem. Could you provide any suggestions?
Thanks in advance!
Let's apply the KISS principle; we don't need to bring in #(freeform). Instead we can separately capture the main line and the continuation lines for the (potentially) multi-line variables. Then, intelligently combine them with #(merge):
#(collect)
Variable Group: #i
variable = #value
long_variable = #l_head
# (collect :gap 0 :vars (l_cont))
#l_cont
# (end)
really_long_variable = #rl_head
# (collect :gap 0 :vars (rl_cont))
#rl_cont
# (end)
# (merge long_variable l_head l_cont)
# (merge really_long_variable rl_head rl_cont)
#(end)
Note that the big indentations in the above are supposed to be literal tabs. Instead of literal tabs, we can encode tabs using #\t.
Test run on the real data with \t replaced by tabs:
$ txr -Bl new.txr data
(i "1" "2")
(value "the value of the variable" "the value of the variable in group 2")
(l_head "the value of the long variable" "this variable might not be that long")(l_cont ("spans across multiple lines") nil)
(rl_head "this variable extends" "neither might this one!")
(rl_cont ("across more than two lines, but it" "is unclear how many lines it will end up extending"
"across ahead of time") nil)
(long_variable ("the value of the long variable" "spans across multiple lines")
("this variable might not be that long"))
(really_long_variable ("this variable extends" "across more than two lines, but it"
"is unclear how many lines it will end up extending" "across ahead of time")
("neither might this one!"))
We use a strict collect with :vars for the continuation lines, so that the variable is bound (to nil) even if nothing is collected. :gap 0 prevents these inner collects from scanning across lines that don't start with tabs: another strictness measure.
#(merge) has "special" semantics for combining lists of strings that haver different nesting levels; it's perfect for assembling data from different levels of collection and is basically tailor made for this kind of thing. This problem is very similar to extracting HTTP, Usenet or e-mail headers, which can have continuation lines.
On the topic of how to write a Lisp function to look ahead in the data, the most important aspect is how to get a handle on the data at the current position. The TXR pattern matching works by backtracking over a lazy list of strings (lines/records). We can use the #(data) directive to capture the list pointer at the given input position. Then we can just treat that as a list:
#(data here)
#(bind tab-start-lines #(length (take-while (f^ #/\t/) here))
Now tab-start-lines has a count of how many lines in the input start with tabs. However, take-while has a termination condition bug, unfortunately; if the following data consists of nothing but one or more tab lines, it misbehaves.⚠ Until TXR 166 is released, this requires a little workaround: (take-while [iff stringp (f^ #/\t/)] here).
Assuming I have the following Perl code open in Vim:
if (#arr = shomething()) {
for (#arr) {
some_function($_->{some_key});
# some
# more
# code
while (some_other_funtion($_)) {
write_log('working');
}
}
}
and the cursor at the beginning of the line with some_function, how I can move the cursor to any of:
the start of the while
the { of the while
the first line inside the while block (with the call to write_log)
Searching for { is not an option, because there could be many of { that do not start new inner code block - for example, see parameter of some_function.
It seems you are defining a “code block” to be { } that contain at least one line. You can most easily search for those just by searching for a { at the end of a line:
/{$
/{ means search for a {, and $ represents an anchor to the end of the line.
There might be cases where a { opens a block, but is not the last character of a line:
while (some_other_funtion($_)) { # this while is very important
write_log('working');
}
To take this into account, do the following search for a { that is not closed on the same line:
/{[^}]*$
/ – search for
{ – a { character
[^}] – followed by any character that is not a }
* – repeated 0 or more times
$ – until the end of the line
(Vim regexes are not always the same as in Perl, but this particular one is.)
You could define a mapping for that second search by putting this in your .vimrc:
noremap <Leader>nb /{[^}]*$<CR>
That would let you jump to the next block by pressing <Leader> (\ by default) n b.
Since it uses :noremap, it affects Select mode too. You won’t want that if your <Leader> is a printable character (which it is by default). In that case, add the line sunmap <Leader>nb below the previous line to fix Select mode.
% , $, and ^ are your best friends. (cursor to matching enclosure, end of line, beginning of line).
At the beginning of your code block there ':1$' , will put your cursor at the first bracket.
% will advance you to the next 'matching' end of your code block, assuming it is balanced. If your code is out of balance, the cursor won't move. It actually counts matching-type opening and closing braces which follow and if there is an imbalance, the cursor will not move. Usually the terminal will beep: as in 'Doh! You have a problem.' It's very useful and it works with '{}[]()'
Good way to check your code and ensure that the end of the block exists. It will skip as many lines as exist between the braces (or parens or brackets) to place the cursor on the matching enclosure.
This file is small but assuming you're on line 1 (:1)
:1$ - end of line first code block
:2 - puts the cursor at the 'f' in 'for' on line 2 rather than the white space preceding.
% - jumps you to the closing ')' on that line.
% - jumps you to the opening '(' on that line.
$ - takes you to the '{' which opens the for loop code
% - jumps the cursor to the ending '}' of the for loop
% - takes you back to the top (% is bi-directional. )
Play with it. There's a reason that Intellij's text editor has a vim mode. It's powerful.
Also, pretty good vim manual here that covers some of this stuff and much more.
https://www.pks.mpg.de/~mueller/docs/suse10.1/suselinux-manual_en/manual/sec.suse.vim.html
As the question suggests I want to comment out some part of a line in MATLAB.
Also I want to comment out some part of a line not till the end of line.
Reason for this is, I have to try two different versions of a line and I don't want to replicate the line twice. I know it is easy to comment/uncomment if I replicate the line , But I want it this way.
Within one line is not possible (afaik), but you can split up your term into multiple lines:
x=1+2+3 ... optional comments for each line
... * factorA ... can be inserted here
* factorB ...
+4;
Here * factorA is commented out and * factorB is used, resulting in the term x=1+2+3*factorB+4.
The documentation contains a similar example, commenting out one part of an array:
header = ['Last Name, ', ...
'First Name, ', ...
... 'Middle Initial, ', ...
'Title']
Nope, this is not possible. From help '%':
% Percent. The percent symbol is used to begin comments.
Logically, it serves as an end-of-line character. Any
following text on the line is ignored or printed by the
HELP system.
So just copy-paste the line, or write a tiny function so that it's easier to switch between versions.
I am working on some old qbasic code. It's a mess with all the Goto statements. Am I correct that the following line will always return?
IF FLAG = 0 THEN TARGET = X: GOSUB 55000: TEMP = XI - TEMP2: RETURN
So if I understand this correctly the colon separates statements on the same line. The if only pertains to TARGET = X. The GOSUB, TEMP =, and RETURN will always execute. Correct?
Part of my confusion is because the very next line reads
IF FLAG = 1 THEN STEP = X: GOSUB 115000
And since the label to the second statement is never used in a GOTO I can't see that it would ever get executed.
Yes, I believe your assessment is correct. The colon is a statement separator that lets you have multiple statements on the same line. Assuming your subroutine at 55000 returns, this line should return as well.
I was wrong. Running this program:
if 1=2 then print "Never printed" : print "how about this?"
print "End of program"
on qb64.net prints only End of program. I assume that its grammar details are the same as Qbasic's, although it is a reverse-engineered effort.
As an aside, this code is written in a pre-QBasic style (e.g. using GOSUB and line numbers). There is a script that often came with QBasic (remline.bas, I believe it was called) that is supposed to help translate these kinds of programs to a newer style. I have never used it myself, though.
I am using vim to edit a shell script (did not use the right coding standard). I need to change all of my variables from camel-hum-notation startTime to caps-and-underscore-notation START_TIME.
I do not want to change the way method names are represented.
I was thinking one way to do this would be to write a function and map it to a key. The function could do something like generating this on the command line:
s/<word under cursor>/<leave cursor here to type what to replace with>
I think that this function could be applyable to other situations which would be handy. Two questions:
Question 1: How would I go about creating that function.
I have created functions in vim before the biggest thing I am clueless about is how to capture movement. Ie if you press dw in vim it will delete the rest of a word. How do you capture that?
Also can you leave an uncompleted command on the vim command line?
Question 2: Got a better solution for me? How would you approach this task?
Use a plugin
Check the COERCION section at the bottom of the page:
http://www.vim.org/scripts/script.php?script_id=1545
Get the :s command to the command line
:nnoremap \c :%s/<C-r><C-w>/
<C-r><C-w> gets the word under the cursor to command-line
Change the word under the cursor with :s
:nnoremap \c lb:s/\%#<C-r><C-w>/\=toupper(substitute(submatch(0), '\<\#!\u', '_&', 'g'))/<Cr>
lb move right, then to beginning of the word. We need to do this to get
the cursor before the word we wish to change because we want to change only
the word under the cursor and the regex is anchored to the current cursor
position. The moving around needs to be done because b at the
start of a word moves to the start of the previous word.
\%# match the current cursor position
\= When the substitute string starts with "\=" the remainder is interpreted as an expression. :h sub-replace-\=
submatch(0) Whole match for the :s command we are dealing with
\< word boundary
\#! do not match the previous atom (this is to not match at the start of a
word. Without this, FooBar would be changed to _FOO_BAR)
& in replace expressions, this means the whole match
Change the word under the cursor, all matches in the file
:nnoremap \a :%s/<C-r><C-w>/\=toupper(substitute(submatch(0), '\<\#!\u', '_&', 'g'))/g<Cr>
See 3. for explanation.
Change the word under the cursor with normal mode commands
/\u<Cr> find next uppercase character
i_ insert an underscore.
nn Search the last searched string twice (two times because after exiting insert mode, you move back one character).
. Repeat the last change, in this case inserting the underscore.
Repeat nn. until all camelcases have an underscore added before them, that is, FooBarBaz has become Foo_Bar_Baz
gUiw uppercase current inner word
http://vim.wikia.com/wiki/Converting_variables_to_camelCase
I am not sure what you understand under 'capturing movements'. That
said, for a starter, I'd use something like this for the function:
fu! ChangeWord()
let l:the_word = expand('<cword>')
" Modify according to your rules
let l:new_var_name = toupper(l:the_word)
normal b
let l:col_b = col(".")
normal e
let l:col_e = col(".")
let l:line = getline(".")
let l:line = substitute(
\ l:line,
\ '^\(' . repeat('.', l:col_b-1) . '\)' . repeat('.', l:col_e - l:col_b+1),
\ '\1' . l:new_var_name,
\ '')
call setline(".", l:line)
endfu
As to leaving an uncompleted command on the vim command line, I think you're after
:map ,x :call ChangeWord(
which then can be invoked in normal mode by pressing ,x.
Update
After thinking about it, this following function is a bit shorter:
fu! ChangeWordUnderCursor()
let l:the_word = expand('<cword>')
"" Modify according to your rules
let l:new_var_name = '!' . toupper(l:the_word) . '!'
normal b
let l:col_b = col(".")
normal e
let l:col_e = col(".")
let l:line = getline(".")
exe 's/\%' . l:col_b . 'c.*\%' . (l:col_e+1) .'c/' . l:new_var_name . '/'
endfu