Last active
February 8, 2020 19:37
-
-
Save db93n2/c914a936c1977a525a58c88d7d03792a to your computer and use it in GitHub Desktop.
๐ (autohotkey) - combine auto-execute sections from #included scripts into your main script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
[settings] | |
save_folder = | |
[script folders] | |
folder_1 = | |
folder_2 = | |
[ignore] | |
C:\Users\documents\example script name.ahk | |
C:\Users\documents\example folder name | |
[stats] | |
last_refresh_time = 20171120064635 | |
a_tick_count = | |
[script info] | |
version = 0.3.6 | |
description = combine auto-execute/exit sections from #included scripts into your main script | |
author = davebrny | |
source = https://gist.github.com/davebrny/c914a936c1977a525a58c88d7d03792a | |
*/ | |
ex_this(byRef script_list="", refresh_all="") { | |
start_time := a_tickCount | |
revert_batch := a_batchLines | |
setBatchLines, -1 | |
iniRead, save_folder, % a_lineFile, settings, save_folder | |
iniRead, last_refresh_time, % a_lineFile, stats, last_refresh_time | |
iniRead, ignore_pattern, % a_lineFile, ignore | |
save_folder := (fileExist(save_folder) ? save_folder : a_temp "\ex_this") | |
fileRead, last_script_list, % save_folder "\script list.txt" | |
;--------------------------------------------- | |
loop, | |
{ | |
iniRead, script_folder, % a_lineFile, script folders, folder_%a_index% | |
if (script_folder = "") | |
continue ; > > > > > > > > > > > > > > > > > | |
loop, files, % script_folder "\*.ahk", FR | |
{ | |
if inStr(ignore_pattern . "`n", a_loopFileDir . "`n") | |
ignore_folder := a_loopFileDir | |
if a_loopFileDir contains %ignore_folder% | |
continue ; > > > > > > > > > > > > > > > | |
if inStr(ignore_pattern, a_loopFileFullPath) | |
continue ; > > > > > > > > > > > > > > > | |
script_list .= (script_list? "`n" : "") . a_loopFileFullPath | |
if (refresh_all) | |
or (a_loopFileTimeModified > last_refresh_time) ; if file has changed since | |
or (a_loopFileTimeCreated > last_refresh_time) ; if newly created (or copied into the folder) | |
or !inStr(last_script_list, a_loopFileFullPath) ; catch the files that have been 'moved' or 'cut' | |
{ | |
fileRead, contents, % a_loopFileFullPath | |
if inStr(contents, "/*") | |
contents := ex_strip(contents) ; strip comment blocks | |
loop, 2 | |
{ | |
type := (a_index = 1) ? "execute" : "exit" ; check for each type | |
if !inStr(contents, ";" . type . "_this") | |
not_using_ex .= type . a_loopFileFullPath "`n" | |
else ; if file is using execute_this or exit_this | |
{ | |
new_text := ex_section(type, contents) ; get execute/exit text | |
stringGetPos, pos, script_folder, \, R1 ; get parent folder name | |
stringMid, parent_folder, script_folder, pos + 2 | |
end_path := strReplace(a_loopFileFullPath, script_folder "\") ; remove dir | |
ex_path := save_folder "\" type "\" parent_folder "\" end_path ; append to ex_this dir | |
fileRead, current_text, % ex_path | |
top_text := " `; " . a_loopFileFullPath . "`n" | |
. " `; ! auto-generated file. any changes made here will be overwritten`n`n" | |
if (current_text != top_text . new_text) | |
{ | |
if fileExist(ex_path) | |
fileDelete, % ex_path | |
else fileCreateDir, % subStr(ex_path, 1, strLen(ex_path) - strLen(a_loopFileName)) | |
fileAppend, % top_text . new_text, % ex_path | |
} | |
} | |
} | |
} | |
} | |
} | |
until (script_folder = "ERROR") ; loop end | |
;----------------------------------------- | |
loop, files, % save_folder . "\*.ahk", FR | |
{ | |
if a_loopFileFullPath contains ~execute_this,~exit_this | |
continue ; > > > > > > > > > > > > | |
type := inStr(a_loopFileDir, "\execute\") ? "execute" : "exit" | |
source_path := ex_source(a_loopFileFullPath) | |
; if file no longer exists, or if it no longer contains execute/exit_this | |
if !inStr(script_list, source_path) or inStr(not_using_ex, type . source_path) | |
fileDelete, % a_loopFileFullPath | |
else %type%_this .= "#include, " a_loopFileFullPath "`n" ; create include list | |
} | |
ex_update_list(execute_this, save_folder "\~execute_this.ahk") | |
ex_update_list(exit_this, save_folder "\~exit_this.ahk") | |
ex_update_list(script_list, save_folder "\script list.txt") | |
iniWrite, % " " a_now, % a_lineFile, stats, last_refresh_time | |
iniWrite, % " " a_tickCount - start_time, % a_lineFile, stats, a_tick_count | |
setBatchLines, % revert_batch | |
} | |
ex_strip(string) { ;# strip out comment blocks | |
original_string := string | |
if inStr(string, "`r`n") | |
stringReplace, string, string, `r`n, `n, all | |
if (subStr(string, 1, 2) = "/*") ; if at first line | |
stringReplace, string, string, % "/*", % "`n/*" | |
strReplace(string, "`n/*", "", block_start) ; get number of blocks | |
strReplace(string, "`n*/", "", block_end) | |
block_count := (block_start > block_end) ? (block_end) : (block_start) | |
loop, % block_count | |
{ | |
if (a_index = 1) ; get text before 1st block | |
{ | |
stringGetPos, block_start, string, % "`n/*", L1 | |
stringMid, first_section, string, block_start, , L | |
new_string .= first_section "`n" | |
} | |
else ; every other loop (text between blocks) | |
{ | |
stringGetPos, block_start, string, % "`n/*", L%a_index% | |
stringMid, middle_sections, string, block_start, , L | |
stringGetPos, block_end, middle_sections, % "`n*/", R1, | |
stringMid, middle_sections, middle_sections, block_end + 5 | |
new_string .= middle_sections "`n" | |
} | |
} ; text after last block | |
stringGetPos, block_end, string, % "`n*/", R1 | |
stringMid, end_section, string, block_end + 5 | |
new_string .= end_section | |
if inStr(original_string, "`r`n") | |
stringReplace, new_string, new_string, `n, `r`n, all | |
return new_string | |
} | |
ex_section(type, contents) { ;# get execute / exit text | |
strReplace(contents, ";" type "_this", "", this_count) | |
loop, % this_count | |
{ | |
stringGetPos, pos, contents, % ";" type "_this", % "L" a_index | |
stringMid, text_after, contents, pos + 1 | |
stringGetPos, pos, text_after, `n, L1 ; the first line after execute_this | |
stringMid, section_start, text_after, pos + 2 | |
stringGetPos, pos, section_start, % ";" type "_end", L1 | |
stringMid, section_block, section_start, % pos, , L | |
section_text .= (section_text ? "`r`n" : "") . section_block | |
} | |
if inStr(section_text, "`r`n`r`n") | |
{ | |
loop, ; remove empty lines | |
stringReplace, section_text, section_text, `r`n`r`n, `r`n, all | |
until !InStr(section_text, "`r`n`r`n") | |
} | |
loop, parse, section_text, `n, `r | |
{ | |
if a_loopField is space | |
continue ; skip lines that contains only spaces or tabs | |
if (inStr(ltrim(a_loopField), ";") = 1) | |
continue ; skip commented lines | |
new_text .= (new_text ? "`r`n" : "") . a_loopField | |
} | |
return new_text | |
} | |
ex_source(ex_path) { ;# get the source/original path from line 1 of the file | |
file := fileOpen(ex_path, "r") | |
source_path := trim(file.readLine(), "`r`n `;") | |
file.close() | |
return source_path | |
} | |
ex_update_list(new_text, list_file) { ;# update the list (if there are changes) | |
file := fileOpen(list_file, "r `n") | |
current_text := file.read() | |
top_text := " `; ! auto-generated file. any changes made here will be overwritten`n`n" | |
new_text := top_text . new_text | |
if (current_text != new_text) | |
{ | |
file := fileOpen(list_file, "w `n") | |
file.write(new_text) | |
} | |
file.close() | |
} | |
::;exe:: ; hotstrings | |
::;exi:: | |
::;exes:: ; (append ex_this source url) | |
::;exis:: | |
ex_type := inStr(a_thisLabel, "exe") ? "execute" : "exit" | |
ex_link := inStr(a_thisLabel, "s") ? " `; source: git.io/vFQ1z" : "" | |
string := ";{1}_this{2}`n;{1}_end" | |
string := strReplace(string, "{1}", ex_type) | |
string := strReplace(string, "{2}", ex_link) | |
send % string | |
return |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ex_this()
if all of your autohotkey scripts are split up into individual files and included into one main script then there can be a bit of going back and forth between the current file and the auto-execute section any time you need to change something there.ย ex_this() solves this problem (in most cases) by letting you add to the auto-execute section (or exit subroutine) from anywhere in your script
it also solves the problem of getting "label not found" errors when you remove a file but forgot to remove the goSub or timer that was in the auto-execute section
another benefit of using this method is that sharing code with others becomes easier since everything is self contained in one file.
if the person youre sharing a script with is also using ex_this() then all they have to do is include it into their own script and reload to get things up and running. ย if theyre not, then the execute/exit tags can act sort of like instructions about which parts need to be copied to auto-execute section of their script
lastly, since the execute/exit tags are just comments, they dont have any effect if someone decides to run the script it on its own
drawbacks
ex_this() copies the code between the execute/exit tags and then stores it in
\AppData\Local\Temp\ex_this\
this means means that msgBox errors will show that location and not the source file, as will certain variables such as a_lineFile.
in certain situations you might be able to work around these problems by using the "goto error" timer below or by using the following function to convert a_lineFile to the actual source file
i havnt tested this it out in all the different situations it could be used in yet so there are probably more drawbacks than the ones listed above
ย
ย
usage
ย
auto-execute example:
if the above was in a standalone script then everything would be executed.
if this was in an included script then only the commands between the tags would run, while the same script settings would be set in the auto-execute section of your main script
ย
when/why files are scanned
ย
disable temporarily
put a space somewhere in the middle of the first tag and then reload your script
;exec ute_this
or put a comment block around the tags
or comment out every line
ย
ignoring files and folders
if you have a lot of scripts that will be scanned every time you use ex_this() then you might be able to cut down the scan time a bit by ignoring certain folders that you know you will never be using the execute/exit tags in:
ย
hotstrings
use
;exe
to add theexecute_this
tags and;exi
to add theexit_this
tagsadd an
s
to the end of these hotstrings to send the tag along with the source url for ex_this()ย
goto error
add the following code to your script to have it open the source file any time it detects a msgBox with an error in the
\ex_this\
folder