Skip to content

Instantly share code, notes, and snippets.

@davebrny
Last active February 21, 2024 08:35
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save davebrny/7dbeda0baea3ec467c804772833fe2a5 to your computer and use it in GitHub Desktop.
Save davebrny/7dbeda0baea3ec467c804772833fe2a5 to your computer and use it in GitHub Desktop.
🏷️ (autohotkey) - add a tagspaces style [tag] to a filename
/*
[tag list]
bank
car
insurance
receipt
tax
[settings]
recent_total = 11
recent_tags =
[script info]
version = 0.4
description = add a tagspaces style [tag] to a filename
author = davebrny
source = https://gist.github.com/davebrny/7dbeda0baea3ec467c804772833fe2a5
*/
#noEnv
#singleInstance, force
onExit, exit_label
iniRead, tag_list, % a_lineFile, tag list
recent := []
iniRead, recent_total, % a_lineFile, settings, recent_total
iniRead, recent_tags, % a_lineFile, settings, recent_tags
loop, parse, % recent_tags, `, , % a_space
recent.push(a_loopField)
groupAdd, file_browsers, ahk_exe explorer.exe
groupAdd, file_browsers, ahk_exe XYplorerFree.exe
hotkey, ifWinActive, ahk_group file_browsers
hotkey, !t, square_menu
return ; end of auto-execute---------------------------------------------------
square_menu:
file_path := get_file()
if (file_path = "")
return ; dont continue
menu, square_menu, add, square tag, add_tag
menu, square_menu, default, square tag
menu, square_menu, disable, square tag
menu, square_menu, add
splitPath, file_path, , dir, ext, filename
tags := get_tags(filename)
if (tags)
{
menu, current_tags, add, select to remove:, remove_tag
menu, current_tags, disable, select to remove:
menu, current_tags, add
loop, parse, tags, `, , % a_space
menu, current_tags, add, % a_loopfield, remove_tag
menu, square_menu, add, current tags, :current_tags
menu, square_menu, add
}
if (tag_list)
{
loop, parse, tag_list, `n, `r
{
menu, tag_list, add, % a_loopfield, add_tag
if already_in(tags, a_loopfield)
menu, tag_list, disable, % a_loopfield
}
menu, square_menu, add, tag list, :tag_list
}
if (tags_in_folder())
{
loop, % in_folder.maxIndex()
{
menu, in_folder, add, % in_folder[a_index], add_tag
if already_in(tags, in_folder[a_index])
menu, in_folder, disable, % in_folder[a_index]
}
menu, square_menu, add, in folder, :in_folder
}
if (recent.maxIndex())
{
menu, square_menu, add
menu, square_menu, add, recent tags:, add_tag
menu, square_menu, disable, recent tags:
menu, square_menu, add
loop, % recent.maxIndex()
{
menu, square_menu, add, % recent[a_index], add_tag
if already_in(tags, recent[a_index])
menu, square_menu, disable, % recent[a_index]
}
menu, square_menu, add
menu, square_menu, add, clear recent, clear_recent
}
menu, square_menu, useErrorLevel
menu, square_menu, show
menu, square_menu, delete
menu, current_tags, delete
menu, tag_list, delete
menu, in_folder, delete
file_path := ""
tags := ""
new_tags := ""
return
get_file() {
if winActive("ahk_class CabinetWClass") ; file explorer
file_path := selected_file_ex()
else if winActive("ahk_exe XYplorerFree.exe") ; xyplorer
file_path := selected_file_xy()
return file_path
}
selected_file_ex() { ; file explorer
for window in comObjCreate("shell.application").windows
{
if (window.hwnd != winExist("a"))
continue
for file in window.document.selectedItems
selected .= (selected ? "`n" : "") . file.path
}
file_path := first_file(selected)
return file_path
}
selected_file_xy() { ; xyplorer
restore_clipboard := clipboardAll
clipboard := ""
send ^{p}
clipWait, 0.3
selected := clipboard
clipboard := restore_clipboard
file_path := first_file(selected)
return file_path
}
first_file(list) {
loop, parse, list, `n, `r
{
if fileExist(a_loopField)
return a_loopField
}
}
get_tags(byRef filename) {
if inStr(filename, "[") and inStr(filename, "]")
{
stringGetPos, pos, filename, [, R1
stringMid, str_right, filename, pos + 2
stringMid, name_without_tags, filename, pos, , L
filename := rTrim(name_without_tags)
stringGetPos, pos, str_right, ], R1
stringMid, tags, str_right, pos, , L
return tags
}
}
already_in(tags, item) {
if inStr(", " tags ", " , ", " item ", ")
return true
}
tags_in_folder() {
global in_folder, dir
in_folder := []
loop, files, % dir "\*", FD
{
splitPath, a_loopFileFullPath, , , , filename
tags := get_tags(filename)
loop, parse, % tags, `, , % a_space
in_folder.push(a_loopField)
}
if (in_folder.maxIndex())
return in_folder
}
remove_tag:
loop, parse, tags, `, , % a_space
{
if (a_loopField != a_thisMenuItem)
new_tags .= (new_tags? ", " : "") . a_loopfield
}
new_path := dir "\" filename . (new_tags ? " [" new_tags "]" : "")
if (fileExist(file_path) = "D")
fileMoveDir, % file_path, % new_path
else fileMove, % file_path, % new_path "." ext
return
add_tag:
new_path := dir "\" filename " [" tags . (tags? ", " : "") . a_thisMenuItem "]"
if (fileExist(file_path) = "D")
fileMoveDir, % file_path, % new_path
else fileMove, % file_path, % new_path "." ext
add_to_recent(a_thisMenuItem)
return
add_to_recent(item) {
global recent, recent_total
for index, value in recent
if (value = item) ; if already in recent
recent.removeAt(index)
recent.insertAt(1, item)
if (recent.maxIndex() > recent_total)
recent.pop()
}
clear_recent:
recent := []
iniWrite, % "", % a_lineFile, settings, recent_tags
return
exit_label:
recent_tags := ""
loop, % recent.maxIndex()
recent_tags .= (recent_tags ? ", " : "") . recent[a_index]
iniRead, ini_value, % a_lineFile, settings, recent_tags
if (recent_tags != ini_value)
iniWrite, % " " recent_tags, % a_lineFile, settings, recent_tags
exitApp
@davebrny
Copy link
Author

davebrny commented Dec 2, 2017

i use TagSpaces to organise my scanned documents but i wanted something a bit more lightweight that would let me quickly add a tag or two without having to open the application.

usage

  • populate the tag list in the ini section at the top of the file and then reload the script to update your changes
  • select a single file or folder in file explorer
  • press alt + t to show the tag menu

tag format

filename [tag1].txt
filename [tag1, tag2, tag3].txt

the square tag has to be at the end of the filename

add a tag
- click on a tag name in the "tag list" sub-menu to have it added to the file.
- the "in folder" sub-menu shows tags that are being used in other files in the same folder.
- once a few tags have been added a "recent tags" section will appear at the bottom of the list

any tags that are already being used in the current file will show as disabled/greyed out

remove a tag
click on one of the tag names in the "current tags" sub-menu to remove it from the filename

@iccm
Copy link

iccm commented Oct 6, 2019

Whow!
This is exactly what I was searching for.
2 questions please:

  1. When I select a tag to a file, it duplicate the file, meaning that I'm left with the old file (without a tag) and a new file with the tag.
    Is there a way just to add a tag and don't copy the file?
  2. When using Hebrew characters, although I save the script in UTF8, I see gibberish in the menu and I cannot use Hebrew tags.
    Do you know how to do that?

Thank you very much!

@haukebasse
Copy link

Hello
Great script! I really like the way you realized the GUI and the functionality!
I think about adapting it to my preferred file manager FreeCommander.
You got any hints for me before I start by digging myself into your code?
Kind regards, Hauke

@davebrny
Copy link
Author

davebrny commented Oct 3, 2020

Hauke

hey glad you like it! i just updated the this with some code i had in another script for using multiple file browsers. just add a new function for freecommander and you can use it as normal :)

@haukebasse
Copy link

Incredible! I only added "FreeCommander.exe" in two places, and then one single more line for getting the file path, and now it already works! So great; thank you!

@science2002
Copy link

science2002 commented Feb 20, 2024

Very helpful script. Many thanks. Two additional features, if it is possible, could improve even more its functionality.

  1. Select the tags with a tick box, instead as now using the click. The advantage would be that more tags could be selected at the same time - by flagging each tick box - and not as now just one tag at the time (also - as alternative - a Ctrl click to select multiple tags could be helpful, in place of the tick boxes).
  2. Using still ^t to make the tag list appear also while saving a file. Once one has written the name of a file in the Window, "Save as...", it would be helpful to add in the name the tags on the fly, so to have the file with tags since its creation, instead of adding them afterwards.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment