I have a txt file named subroutines.ahk in it is the below hotstring.
::btw::Thank you for the help
I know if I want to run my hotstring from another script all I have to do is include it in that script using:
#include subroutines.ahk
But I dont want to do that Instead from another script I want to Loop read the contents of subroutines.ahk and load the hotstring variables that way .
Loop, read,subroutines.ahk
{
Loop, parse, A_LoopReadLine, %A_Tab%
{
MsgBox, Field number %A_Index% is %A_LoopField%.
}
}
I would really appreciate your help on how I can load my hotstring variables into another script that way.
I plan to encode the hotsrings in subroutines.ahk and than decode the contents of the subroutines.ahk in the second program and load it into memory.
In the above example though i am first trying to figure out how I can loop read the txt file and run the hot strings from there.
Demonstrates the use of hotkeys that map to dynamic values
; Replace hash values with whatever method you use to decrypt your hotstrings
decrypted := {abc: "alpha", def: "beta"}
::abc::
Send % decrypted["abc"]
return
::def::
Send % decrypted["def"]
return
When you type "abc", "alpha" appears instead
# directives are processed only once when the script is launched. To work around this limitation, you can use reload to execute dynamically generated script that includes # directives.
Code sample:
When F1 is pressed, use the contents of "subroutines.ahk" to generate and run code that utilizes # directives:
F1:: reload_hotstrings()
#Include temp.ahk
reload_hotstrings()
{
FileDelete temp.ahk
loop read, subroutines.ahk
{
MsgBox Hotstring number %A_Index% is %A_LoopReadLine%.
FileAppend %A_LoopReadLine%`n, temp.ahk
}
reload
}
Alternatively, if you want to automatically generate hotkeys code whenever autohotkey starts:
I'm using source.dat for your subroutines.ahk file
Code sample:
FileGetTime source_time, source.dat
FileGetTime compiled_time, compiled.ahk
; calculate time difference between source and compiled files
EnvSub source_time, %compiled_time%, Seconds
; compile and run if source newer
if source_time > 0
{
FileDelete compiled.ahk
loop read, source.dat
{
FileAppend %A_LoopReadLine%`n, compiled.ahk
}
reload
}
#Include compiled.ahk
Related
I am writing a script to access a function that has been written in another script.
When I run the second script the error is that the function is undefined.
I have been working backwards and am currently trying to get the function to work in the command window.
The function file has appeared in the current folder window. When it is highlighted all functions and parameters are displayed in the window below (displays the file name on top then the file contents).
I am still getting a function is undefined when I copy and paste the functions call from the script into the command window.
I tried rebuilding the functions individually in separate scripts, but I am still receiving an error message.
I have made sure the are in the same folder, and are spelled exactly the same, what am I doing wrong?
'''
%file name Lab_5_functions.m
function[vel] = velocity (g,m,co_d,t)
vel= ((g*m)/co_d)^(1/2)*tanh(((g*co_d)/m)^(1/2)*t);
end
function [dvel]= dvelocity (g,m,co_d,t)
dvel=(((.5*(g*m)/co_d)^(1/2)*tanh(((g*co_d)/m).^(1/2)*t_sec))-(((g*t)/(2*m))*(sech(((g*co_d)./m).^(1/2)*t))));
end
'''
v=velocity(1,2,3,4)
%error message below:
Undefined function or variable 'velocity'.
'''
Thanks
-MK
Matlab is searching for functions using filenames. So you define a single public function myfunc in a file myfunc.m.
You can define additional functions in that file, but they will not be accessible outside that .m file.
MATLAB looks for filenames to find the functions and expects the first line of that file to be a function definition.
For example: myfunc.m
function output = myfunc(input)
If you do want many functions in one file (like a module/library), I have used a work-around before: write all your functions in the file, then include an if-else block to call the correct function. Multiple arguments can be parsed with some simple checks (see nargin function). It is a less elegant solution; I only use it if I have many simple functions and it would be plain annoying to have heaps of .m files.
Here is a simple example:
Call the file: myfunc.m
function output = myfunc(fn, arg1, arg2, ...)
function out = func1(arg1, arg2, ...)
out = 0
if strcmp(fn, 'func1')
if nargin == 2
output = func1(arg1)
end
elseif strcmp(fn, 'func2')
...
end
I have an autohotkey script(A) that write another script(B).
The important line in my script(A):
InputBox variable, Variable
Send %variable%
Then, if i input:
helloworld{enter}
it will write "helloworld" and insert a new line in my script(B) instead of just writing "{enter}"
How do I force it to write %variable% without interpreting it beforehand ?
I agree with the other answer that using FileAppend would be a better method. However, if you truly want to accomplish this using the send command, then you need to use {raw} mode. You can read about {raw} in the documentation:
https://autohotkey.com/docs/commands/Send.htm
InputBox variable, Variable
Send, {raw}%variable%
The simplest way to write another script (scriptB) from scriptA is to use FileAppend:
variable = helloworld
FileAppend,
(
; a line of code
Send %variable%{enter}
; another line of code
)
,C:\scriptB.ahk
Run, edit "C:\scriptB.ahk"
; or:
; Run, C:\scriptB.ahk
or
InputBox variable, Variable, Enter a variable:
if not ErrorLevel
{
FileAppend,
(
; a line of code
Send %variable%{enter}
; another line of code
)
,C:\scriptB.ahk
Run, edit "C:\scriptB.ahk"
; or:
; Run C:\scriptB.ahk
}
return
In my #include files, I want to output debug messages that include the line number and the script name, but while the #ScriptLineNumber macro emits the line number of the #include file it's in, there is no way to emit the current file's filename. I would like to define a user macro something like #ThisScriptName in a debug message like this:
_DebugOut("+++:" & #ThisScriptName & ":" & #ScriptLineNumber & ": some text")
The output would look something like this:
+++:SampleIncludedFile.au3:127: some text
There is no way to do this so that it gives the included file name using any of the macros available.
The easiest alternative method is to use a variable that is overwritten at the top of each include file.
ExampleScript.au3:
#include "ExampleInclude.au3"
Global $ThisScriptName = "ExampleScript"
ConsoleWrite("Hello From: " & $ThisScriptName & #LF)
ExampleInclude.au3:
; #include <...>
Global $ThisScriptName = "ExampleInclude"
ConsoleWrite("Hello From: " & $ThisScriptName & #LF)
With this approach it is important that the variable is defined after the other files you are including.
Other alternatives could be using a preprocessor, either writing one yourself or using one of the various ones others have written already. This could be as simple as just replacing every occurrence of #ThisScriptName with the string version of the file.
I have the below simple code, which sends keystrokes for text in the clipboard with a 15ms delay in between characters (I use this to traverse huge lists of treeview elements).
Issue: If I have copied 'text1' to clipboard, followed by 'text2', this script outputs 'text1text2' instead of 'text2' alone.
If I reload the script, then it prints 'text2'.
Is there a mistake in the below code, or is it a bug in implementing %clipboard% in Autohotkey 1.1.14.03 ?
#v::
textToType=" "
textToType=%clipboard%
LoopCount:=StrLen(textToType)
;StringLen, LoopCount, textToType
Array%LoopCount%:=textToType
loop %LoopCount%
{
theChar:=Array%A_Index%
Send %theChar%
sleep 15
}
return
Update: Thanks for pointing out smarter ways of doing this, but I would still like to figure out what is wrong in the above piece of code.
Update 2:
The mistake was in my understanding of the AHK syntax. Array%LoopCount%:=textToType assigns the whole string value in textToType to the (LoopCount)th STRING element of the STRING array named 'Array'.
Update 3:
(Thanks #John Y for clarifying)
Actually, there's no "declared" array at all, in a traditional sense. You just have a bunch of individual variables, dynamically created as needed, that happen to have names with numbers at the end. Array1 and Array2 are not elements in some Array object. They are just two completely independent variables. AutoHotkey provides a way to glue numbers onto the ends of names, so you can use them like an array.
The reason your script doesn't work properly is because you're using a pseudo-array to store different words from your clipboard.
I've commented up your code to explain what it does:
#v::
textToType := "" ; Empty variable
textToType := Clipboard ; Move clipboard into variable
; Get lenght of the word
; Used as array index / loop count
LoopCount := StrLen(textToType)
; Put the clipboard in an array at index 'LoopCount'
Array%LoopCount% := textToType
; Loop through the array as many times
; as the string is long
Loop % LoopCount
{
; Retrieve the word at this index in the array
theChar := Array%A_Index%
; Send the whole word
Send, % theChar
sleep 15
}
return
Instead of sending each character at a time, you're sending whole words from specific indexes in your Array array.
Say you copy the word Dragon, that word is 6 letters long. So you'd put that in Array6, then you'd loop through your array 6 times using the same variable. At which point the loop would take each index at a time and move it into theChar. On your 6th lap in the loop you'd put Array6 into theChar and print the whole word at once.
Then you copy the word Stackoverflow. That's going to go into Array13, and we're going to loop 13 times. On the 6th lap we're going to print out Dragon which is in Array6, and then keep going until we reach 13 where we'll print Stackoverflow since that is in Array13.
So that's why your script isn't doing what you want it to. Hopefully this helps a little.
See the code sample alpha bravo posted, that's the correct way of achieving what you want to do.
keep it simple
#v::
loop Parse, Clipboard
{
Send %A_LoopField%
sleep 15
}
return
There must be a bug in implementation of clipboard assignment in AHK. With the below code, the behaviour of AHK is that everytime the value of dir is accessed, AHK fetches the latest value from clipboard, instead of fetching the value of dir at the time the script was activated.
; Remove all CR+LF's from the clipboard contents:
dir = %clipboard%
sleep 100
dir := StrReplace(dir, "`r`n")
EDIT:
To fix this, I added 1 second sleep before clipboard assignment code:
sleep 1000
; Remove all CR+LF's from the clipboard contents:
dir = %clipboard%
dir := StrReplace(dir, "`r`n")
100 millisecond sleep didn't seem to work.
Accessing value of dir now only gives value of last clipboard assignment at activation.
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