2024-01-29 19:55:27 +00:00
; This script runs on AutoHotkey v2.
;
; I tried the VS Code extension "Command on All Files" first: https://marketplace.visualstudio.com/items?itemName=rioj7.commandOnAllFiles
; but it didn't work with the "cSpell.addIssuesToDictionary" command.
; I think it was too fast, and the spell checker didn't have time to run.
;
; A better solution would be to:
; - Improve the "Command on All Files" extension:
; - add delay options
; - add a dry run mode, which I had to work around by setting it to a near-no-op command
; - just listing the files would be a lot nicer than opening them all one by one
; - unify file matching; you shouldn't have to specify a list of file extensions to include, it should be a glob like the exclusions
; Or:
; - Add a command to the cspell-cli to accept spellings
; Or:
; - Implement an external Node.js script using cspell's API (but that's less helpful than making a PR)
2024-01-29 07:35:50 +00:00
root := A_ScriptDir "\..\*"
ignoreFolders := [
".git",
".history",
"node_modules",
"lib",
"out",
"localization",
2024-01-29 08:22:55 +00:00
]
ignoreExtensions := [
"png",
"gif",
"jpg",
"jpeg",
"svg",
"cur",
"ico",
"icns",
"wav",
2024-01-29 07:35:50 +00:00
]
command := "cSpell.addIssuesToDictionary"
2024-01-29 08:22:55 +00:00
beforeRunInfo := "This script is designed to add all spelling issues to the dictionary.`nTo use it to prune the dictionary of no-longer-needed words, you must empty the dictionary first.`n`nThis script will run the VS Code command '" command "' on all files in the directory '" root "'.`n`n"
2024-01-29 09:13:19 +00:00
delayBeforeCommand := 2000 ; Give enough time for spell checker to run
delayAfterCommand := 2000 ; Give enough time for CSpell to update the dictionary
closeFileAfterCommand := false
2024-01-29 19:55:27 +00:00
appName := "VS Code Automation"
popup := Gui(, appName)
popup.Opt("+AlwaysOnTop +Disabled -SysMenu +Owner") ; +Owner avoids a taskbar button.
popup.Add("Text", , "`nPress Esc to stop the script.`n`n")
statusBar := popup.Add("StatusBar")
2024-01-29 07:35:50 +00:00
2024-01-30 01:48:33 +00:00
windowId := WinExist("ahk_exe Code.exe")
2024-01-29 07:35:50 +00:00
IsIgnoredPath(path) {
2024-01-29 09:13:19 +00:00
SplitPath path, &name, &dir, &ext, &nameNoExt, &drive
2024-01-29 08:22:55 +00:00
for _, ignoreExtension in ignoreExtensions {
if (StrLower(ext) = ignoreExtension) {
return true
}
}
2024-01-29 07:35:50 +00:00
parts := StrSplit(path, "\")
for index, part in parts {
for _, ignoreFolder in ignoreFolders {
if (part = ignoreFolder) {
return true
}
}
}
2024-01-29 08:22:55 +00:00
2024-01-29 07:35:50 +00:00
return false
}
2024-01-29 08:22:55 +00:00
Automate() {
targets := []
2024-01-29 07:35:50 +00:00
; Loop through files (F) recursively (R)
2024-01-29 09:13:19 +00:00
loop files, root, "FR"
2024-01-29 07:35:50 +00:00
{
if (IsIgnoredPath(A_LoopFileFullPath)) {
continue
}
2024-01-29 08:22:55 +00:00
targets.Push(A_LoopFileFullPath)
2024-01-29 07:35:50 +00:00
}
2024-01-29 08:22:55 +00:00
if (targets.Length = 0) {
2024-01-29 07:35:50 +00:00
MsgBox "No files found for pattern: " root
return
}
2024-01-29 08:22:55 +00:00
2024-01-29 19:55:27 +00:00
; Focus VS Code before confirmation to avoid confusion between multiple VS Code windows
2024-01-29 09:13:19 +00:00
try {
2024-01-30 01:48:33 +00:00
WinActivate { Hwnd: windowId }
2024-01-29 09:13:19 +00:00
} catch TargetError as e {
2024-01-29 19:55:27 +00:00
MsgBox "Could not find VS Code window. Please open it and try again.", appName, 0x10
2024-01-29 09:13:19 +00:00
return
}
2024-01-29 08:22:55 +00:00
; Ask for confirmation
2024-01-29 19:55:27 +00:00
if MsgBox(beforeRunInfo "Found " targets.Length " files. Continue?", appName, 4) = "No" {
if MsgBox("Copy file paths to clipboard?", appName, 4) = "Yes" {
2024-01-29 08:22:55 +00:00
A_Clipboard := Join("`n", targets)
}
return
}
RunCommandOnFiles(targets)
}
RunCommandOnFiles(targets) {
2024-01-29 09:13:19 +00:00
popup.Show("NoActivate") ; NoActivate avoids deactivating the currently active window.
2024-01-29 08:22:55 +00:00
for index, target in targets {
2024-01-29 09:13:19 +00:00
statusBar.SetText(index "/" targets.Length)
2024-01-30 01:48:33 +00:00
try {
RunCommandOnFile(target)
} catch TargetError as e {
2024-01-29 19:55:27 +00:00
popup.Destroy()
2024-01-30 01:48:33 +00:00
MsgBox "Lost VS Code window. Please open it and try again.`n`n" index " out of " targets.Length " files were processed.", appName, 0x10
2024-01-29 19:55:27 +00:00
return
}
2024-01-29 08:22:55 +00:00
}
2024-01-29 09:13:19 +00:00
popup.Destroy()
2024-01-29 08:22:55 +00:00
MsgBox "Processed " targets.Length " files."
2024-01-29 07:35:50 +00:00
return
}
2024-01-29 19:55:27 +00:00
2024-01-30 01:48:33 +00:00
SendToVSCode(keys) {
; ControlSend(keys, , { Hwnd: windowId })
WinActivate { Hwnd: windowId }
Send keys
}
RunCommandOnFile(target) {
2024-01-29 08:22:55 +00:00
; Open file in VS Code using Ctrl+P file switcher
2024-01-30 01:48:33 +00:00
SendToVSCode "^p"
2024-01-29 08:22:55 +00:00
Sleep 100
2024-01-30 01:48:33 +00:00
SendToVSCode target
2024-01-29 08:22:55 +00:00
Sleep 100
2024-01-30 01:48:33 +00:00
SendToVSCode "{Enter}"
2024-01-29 09:13:19 +00:00
Sleep delayBeforeCommand
2024-01-29 08:22:55 +00:00
; Run command via F1 command palette
2024-01-30 01:48:33 +00:00
SendToVSCode "{F1}"
2024-01-29 08:22:55 +00:00
Sleep 100
2024-01-30 01:48:33 +00:00
SendToVSCode command
2024-01-29 08:22:55 +00:00
Sleep 100
2024-01-30 01:48:33 +00:00
SendToVSCode "{Enter}"
2024-01-29 09:13:19 +00:00
Sleep delayAfterCommand
2024-01-29 08:22:55 +00:00
; Close the file (optional)
2024-01-29 09:13:19 +00:00
if closeFileAfterCommand {
2024-01-30 01:48:33 +00:00
SendToVSCode "^w"
2024-01-29 09:13:19 +00:00
}
2024-01-29 08:22:55 +00:00
}
2024-01-29 07:35:50 +00:00
Join(sep, items) {
str := ""
for index, item in items {
str .= item . sep
}
return SubStr(str, 1, -StrLen(sep))
}
; Escape hatch
Esc:: {
ExitApp
}
2024-01-29 19:55:27 +00:00
Automate()
ExitApp()