Autohotkey IniRead pass section name as variable in AHK - autohotkey

I have the following tiny .ini file:
["General"]
"runs"="3"
When using this code to read the file, I get a message box stating the correct number of runs
path := A_ScriptDir "\setup.ini"
IniRead, temp, % path, "General", "runs"
MsgBox, % temp
When I try to pass General as a variable, the message box outputs "ERROR"
path := A_ScriptDir "\setup.ini"
iniSection := "General"
IniRead, temp, % path, % iniSection, "runs"
MsgBox, % temp
I tried enclosing the variables in %-signs, instead of just prefixing them, but it does not make a difference.
Any help is appreciated!

Variable names in an expression are not enclosed in percent
signs. Consequently, literal strings must be enclosed in double
quotes to distinguish them from variables.
To include an actual quote-character inside a literal string, specify
two consecutive quotes:
iniSection := """General"""

Related

Folding the variable name

I want to folding tha variable name
code
numberOfInstNext := Array("","","","","","","","","","","")
numberOfInstNext[1] := 777
i := 1
I tried
msgbox %numberOfInstNext[i]%
error:
The following variable name contains an illegal character 'numberOfInstNext[i]'
Expressions says
An expression can be used in a parameter that does not directly
support it by preceding the expression with a percent sign and a space or tab.
This technique is often used to access arrays.
msgbox % numberOfInstNext[i]
I find the easiest and most scalable solution is to just assign a tmp variable each time you want to access an indexed array.
tmp := numberOfInstNext[i]
msgbox the value is %tmp%!

How can AutoHotkey instance variables be used in WinTitle parameters?

Let's say I have a function to get the window title of a process using its HWND id:
GetWindowTitle(hwnd) {
WinGetTitle, title, ahk_id %hwnd%
return title
}
So far, so good. It works like a charm. So, let's say I am trying to wrap some functionality within a class, in this fashion:
class RunningProcess {
hwnd := ""
windowTitle := ""
__New(hwnd) {
this.hwnd := hwnd
this.windowTitle := GetWindowTitle()
}
GetWindowTitle() {
WinGetTitle, title, ahk_id %this.hwnd%
return title
}
}
The aforementioned code fails to load with the following message:
The following variable name contains an illegal character: "this.hwnd".
I have tried several alternatives in order to use the instance variable hwnd as a WinTitle argument in WinGetTitle, to no avail. The only one that works for me involves using a local variable which grabs the contents of this.hwnd and then using the local variable as a WinTitle argument, like this:
GetWindowTitle() {
foo := this.hwnd
WinGetTitle, title, ahk_id %foo%
return title
}
However, this is less than ideal, as you might guess, at least in my opinion.
Is there a way to use this.hwnd as a WinTitle argument right off the bat?
Thanks!
I'd call it a classic case of having trouble with the legacy vs modern expression syntax.
Refreshing to see it this way though, usually people with the issue are writing 2007 level AHK, but nice to see you're writing modern AHK.
So anyway, forget about using %% to refer to variables. That's the legacy AHK way. In a modern expression statement you just type the name of the variable to refer to is, for example your assignments with the := operator are just fine that way, because it's using the modern expression syntax (= to assign would be the legacy way)
However, pretty much all commands, that haven't been replaced with more modern function, still use the legacy syntax on every parameter (unless otherwise specified in the documentation).
So, you're going to have to set the parameter to evaluate an expression, instead of expecting a legacy text parameter. To do that, you start off the parameter with a single % followed up with a space.
So your WinGetTitle command should look like this:
WinGetTitle, title, % "ahk_id " this.hwnd
Quotation marks around ahk_id , because that's how you specify a string in an expression, and then just type in the variable you want to concatenate to that string. The concatenation operator . could be used here like so % "ahk_id " . this.hwnd, but it's totally redundant and looks weird in my opinion as well.
Also, your call to the GetWindowTitle() function in the initializer __New is going to need a this. in front of it.
And initializing the instance variables to nothing is redundant as well. You can remove that if you want.
Finished product:
MyCoolObject := new RunningProcess(WinExist("A"))
MsgBox, % "The handle of currently active window is: " MyCoolObject.hwnd "`nAnd its title is: " MyCoolObject.windowTitle
class RunningProcess
{
__New(hwnd)
{
this.hwnd := hwnd
this.windowTitle := this.GetWindowTitle()
}
GetWindowTitle()
{
WinGetTitle, title, % "ahk_id " this.hwnd
return title
}
}
To learn more about legacy syntax vs expression syntax, see for example this page from the documentation:
https://www.autohotkey.com/docs/Language.htm

Shortcut for saving file in current directory with correct name?

Is there any shortcut for saving an open file into the current directory with the current name? If I download multiple files with the same name they go into my Downloads folder and they end up with names like function (1).m instead of function.m.
At this point it's easy to open the file and see the contents by opening the file from my web browser- MATLAB sees the file extension and opens it. However, if it's a function, I have to Save As and move/rename the file before I'm able to use the code.
Edit: Since MATLAB insists that the file name be the same as the function name I'm hoping that there's a shortcut that saves an open file directly to the current MATLAB path and names it appropriately.
Since MATLAB convention is that the file name is the same as the function name I'm hoping that there's a shortcut that saves an open file directly to the current MATLAB path and names it according to the function name specified in the file.
You will need a directory which is always on the Matlab path. This can be achieved by adding one in the startup.m script.
Then you should save the below function savefunc.m to that directory, so you can always call it.
function savefunc(FuncName, Directory)
% Set directory if not given, default is working directory
if nargin < 2; Directory = pwd; end
% Get active document
ActiveDoc = matlab.desktop.editor.getActive;
% Set FuncName if not given, or if FuncName was empty string
if nargin < 1 || strcmp(FuncName, '');
% Get function name
FuncName = ActiveDoc.Text; % Entire text of document
% Could use indexing to only take first n characters,
% and not load entire string of long function into variable.
% FuncName = ActiveDoc.Text(1:min(numel(ActiveDoc.Text), n));
FuncName = strsplit(FuncName, '('); % Split on parenthesis
FuncName = FuncName{1}; % First item is "function [a,b,c] = myFunc"
FuncName = strsplit(FuncName, ' '); % Split on space (functions don't always have equals)
FuncName = strtrim(FuncName{end}); % Last item (without whitespace) is "myFunc"
end
% Save the file
saveAs(ActiveDoc, fullfile(Directory, [FuncName, '.m']));
end
Now, say you have just created the following Untitled.m:
function [a,b,c] = mytest()
a = 1; b = 1; c = 1;
end
The shortcut: just have Untitled.m open, and type into the Command Window
savefunc()
Untitled.m will be saved as mytest.m in the current working directory. Notice you can also pass a different function name and save-as directory if you wish, making this useful for other occasions.
You can pass an empty string as the FuncName if you want to specify the directory but use the auto-naming.
You could extend this using matlab.desktop.editor.getAll to get all open documents, then loop through them for saving.
For more info, type help matlab.desktop.editor in the Command Window, online documentation seems lacking.
matlab.desktop.editor: Programmatically access the MATLAB Editor to open, change, save, or close
documents.
Finally, note there is no need for a "Save successful" type message, since you will see the file name change, and also receive an error if it fails (from the saveAs docs):
If any error occurs during the saveAs operation, MATLAB throws a MATLAB:Editor:Document:SaveAsFailed exception. If the operation returns without an exception being thrown, assume that the operation succeeded.

How to save the command history in a text file in MATLAB

I want to save the value of a variable from MATLAB command history in a text. I am trying the command:
Save([d:/work/abc.txt], 'z1', '-ASCII');
An error appears
Error: input charecter is not valid in MATLAB environment or expression.
What you are missing are the quotes within the brackets for denoting string.
['string']
You should use save (with lower case for "s").
Also the filename should be defined as a string: enclose it withi two '; also you do not need the [] unless, for example, you want to build a string using a variable and / or any function to create part of the filename (e. g.
['d:/work/abc_' num2str(k) '.txt']
assuming k value is 3) to get d:/work/abc_3.txt
Try change your code to:
save(['d:/work/abc.txt'], 'z1', '-ASCII');
Hope this helps.
Qapla

Displaying List of AutoHotkey Hotkeys

I’ve written script that contains numerous hotkeys (general structure is as below). I would like to create another one that when pressed displays a list of all of the hotkeys and their corresponding descriptions that the script contains in a nice, formatted table.
The formatting and display are tenuous since AutoHotkey’s output is limited to message-boxes, but possible. More problematic is getting the hotkeys and corresponding descriptions.
The hotkeys all call the same function with different arguments. I considered adding a variable to the function so that depending on the value, the function either performs the normal function when triggered by the normal hotkeys, or builds a string or something when triggered from the special display hotkey.
I cannot figure out a way to programmatically access the script’s hotkeys at all. I checked the docs and there don’t seem to be any A_ variables that can be used for this purpose, nor does the Hotkey command lend itself well (it can be used to test if a hotkey exists, but looping through the innumerable combinations is, at best, tedious).
Failed attempts:
I tried using Elliot’s suggestion of parsing the script itself (replacing the path with %A_ScriptFullPath%, and while it does work for a raw script, it does not when the script is compiled
I tried assigning the entire hotkey section of the script to a variable as a continuation section and then parsing the variable and creating hotkeys using the Hotkey command. This worked well right up until the last part because the Hotkey command cannot take arbitrary commands as the destination and requires existing labels.
The ListHotkeys command is not applicable because it only displays the hotkeys as plain text in the control window.
Does anyone know how I can display a list of the hotkeys and either their corresponding arguments or comments?
Example script:
SomeFunc(foobar)
{
MsgBox %foobar%
}
!^#A::SomeFunc("a") ; blah
^+NumpadMult::SomeFunc("c") ; blivet
^+!#`::SomeFunc("b") ; baz
^#Space::SomeFunc("d") ; ermahgerd
…
Example desired “outputs”:
C+A+ W+ A a | C+ S+ NumpadMult b
------------------+----------------------
C+A+S+W+ ` c | C+ W+ Space d
    or
Ctrl Alt Shift Win Key Action
-----------------------------------------
× × × A blah
× × NumpadMult baz
× × × × ` blivet
× × Space ermahgerd
etc.
The only thing I can think of is to read each line of your script individually and parse it. This code reads your script (script.ahk) one line at a time and parses it. This should get you started. Additionally, you could parse the line to check for the modifiers as well.
Loop
{
FileReadLine, line, C:\script.ahk, %A_Index%
if ErrorLevel
break
If Instr(line, "::")
{
StringSplit, linearray, line, ::,
key := linearray1
StringSplit, commandarray, linearray3, `;
action := commandarray2
hotkeyline := "key: " . key . "`tAction: " . action
final .= hotkeyline . "`r"
}
}
msgbox % final
return
I found a solution. It is not perfect (or ideal), and hopefully a proper, built-in method will become available in the future, but it works well (enough) and for raw and compiled scripts.
What I did was to use the FileInstall command which tells the compiler to add a file to the executable (and extract it when run).
Sadly, the FileInstall command will not allow the use of variables for the source file, so I cannot simply include the script itself (FileInstall, %A_ScriptFullPath%, %A_Temp%\%A_ScriptName%, 1).
As a work-around, I ended up extracting all of the desired hotkeys to a second file which I then parse as Elliot suggested, then delete, and #Include at the end of my script (it must be at the end since hotkeys will terminate the autoexecute section).
;;;;; Test.ahk ;;;;;
; Add hotkey file to executable and extract to Temp directory at runtime
FileInstall, Hotkeys.ahk, %A_Temp%\Hotkeys.ahk, 1
Loop
{
;Read a line from the extracted hotkey script and quit if error
FileReadLine, line, %A_Temp%\Hotkeys.ahk, %A_Index%
if ErrorLevel
break
;Trim whitespace
line=%line%
; Parse the line as in Elliot’s answer, but with tweaks as necessary
ParseHotkey(line)
…
}
FileDelete, %A_Temp%\Hotkeys.ahk ; Delete the extracted script
DisplayHotkeys() ; I ended up bulding and using a GUI instead
#Include, Hotkeys.ahk ; It is included at compile-time, so no A_Temp
;;;;; Hotkeys.ahk ;;;;;
z::MsgBox foo
y::MsgBox bar