Fun with AHK

A place to collect and/or link to AutoHotKey resources for use in Obsidian. Continuing the discussion from AHK repository:

zid = zettelkasten ID
From @crabtree


Send an email directly from inside Obsidian

I blagged the following from the ConnectedText forum. It was written by Manfred Keuhn

` & m:: ;send e-mail
Gui, Add, Edit, W300 vemail,
Gui, Add, Edit, W300 vsubject,
Gui, Add, Edit, W300 R20 vbody,
Gui, Add, Button, Default, Send
Gui, Show
Return,
ButtonSend:
Gui, Submit, NoHide
if email = Email
{
Return,
}
if message = Message
{
Return,
}
else
Run, mailto:%email%?subject=%Subject%&body=%body%
Gui destroy
return

Split the pane vertically and create a new file

@kiriappee on Obsidian forum

#IfWinActive ahk_exe Obsidian.exe
^+n::
Send ^pSplit vertically{Enter}^n
return

Entry form for bibliographical (Book) data

Adapted from the ConnectedText Forum, by @keuhnm. It creates links for the author, the title, and the publisher. The backtick hotkey might be a bit troublesome if you ever do any code highlighting.

` & b::
Gui, Add, Text, x6 y17 w80 h20 , Author:
Gui, Add, Text, x6 y47 w80 h20 , Title:
Gui, Add, Text, x6 y77 w80 h20 , Place:
Gui, Add, Text, x6 y107 w80 h20 , Publisher:
Gui, Add, Text, x6 y137 w80 h20 , Year:
Gui, Add, Edit, x55 y17 w380 h20 vContent1
Gui, Add, Edit, x55 y47 w380 h20 vContent2 
Gui, Add, Edit, x55 y77 w380 h20 vContent3
Gui, Add, Edit, x55 y107 w380 h20 vContent4
Gui, Add, Edit, x55 y137 w180 h20 vContent5 
Gui, Add, Button, x106 y167 w100 h30, Enter ; The label ButtonEnter will be run when the button is pressed.
Gui, Add, Button, x296 y167 w100 h30 , Cancel ; The label ButtonCancel will cancel action but keep script running.
Gui, Show, x350 y182 h210 w461, New Entry
Return ; End of auto-execute section. The script is idle until the user does something.
GuiClose:
   ButtonCancel:
     Gui,Destroy
     Return
   ButtonEnter:
     Gui, Submit  ; Save the input from the user to each control's associated variable.
Gui,Destroy
Send [[%content1%]] (%content5%) *[[%content2%]]*. %content3%: [[%content4%]]`n`n
return

Entry form for bibliographical (Journal ) data
Adapted from the above.

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
#SingleInstance,Force ; Only launch 1 instance of this script.
;~ #Persistent ;Will keep it running...


` & j::
Gui, Add, Text, x6 y17 w80 h20 , Author:
Gui, Add, Text, x6 y47 w80 h20 , Title:
Gui, Add, Text, x6 y77 w80 h20 , Vol-Iss:
Gui, Add, Text, x6 y107 w80 h20 , Journal:
Gui, Add, Text, x6 y137 w80 h20 , Year:
Gui, Add, Text, x226 y137 w80 h20 , Pages:
Gui, Add, Text, x6 y167 w80 h20 , URL:
Gui, Add, Edit, x55 y17 w380 h20 vContent1
Gui, Add, Edit, x55 y47 w380 h20 vContent2 
Gui, Add, Edit, x55 y77 w380 h20 vContent3
Gui, Add, Edit, x55 y107 w380 h20 vContent4
Gui, Add, Edit, x55 y137 w160 h20 vContent5 
Gui, Add, Edit, x275 y137 w160 h20 vContent6 
Gui, Add, Edit, x55 y167 w380 h20 vContent7
Gui, Add, Button, x106 y207 w100 h30, Enter ; The label ButtonEnter will be run when the button is pressed.
Gui, Add, Button, x296 y207 w100 h30 , Cancel ; The label ButtonCancel will cancel action but keep script running.
Gui, Show, x350 y182 h255 w461, New Entry
Return ; End of auto-execute section. The script is idle until the user does something.
GuiClose:
   ButtonCancel:
     Gui,Destroy
     Return
   ButtonEnter:
     Gui, Submit  ; Save the input from the user to each control's associated variable.
Gui,Destroy
Send [[%content1%]] (%content5%) '[[%content2%]]'. *[[%content4%]]*, %content3%, %content6%. %content7%`n`n
return
7 Likes
1 Like
1 Like
2 Likes

Windows: Copy Path with control+shift+7 and paste it with Link format [Link](file:///…). Also copy Chrome URL and paste it Title

I put some code together and here is the result:

^+7:: ; Ctrl+Shift+7 (/)
Clipboard := “”
Send ^l
while !Clipboard {
Sleep, 50
Send ^c
}
Send {End}
WinGetActiveTitle, title

If !WinActive(“ahk_class Chrome_WidgetWin_1 ahk_exe chrome.exe”)
{
;Perform the RegEx find and replace operation,
;where the needle is what we want to replace.
haystack := Clipboard
needle := “\”
replacement := “/”
result := RegExReplace(haystack, needle, replacement)
haystack := result
needle := " "
replacement := “%20”
result := RegExReplace(haystack, needle, replacement)
;Empty the Clipboard
Clipboard =
;Copy the result to the Clipboard.
Clipboard := result
Clipboard := “[” . title . “](file:///” . Clipboard . “)”
;Wait for the Clipboard to fill.
ClipWait
return
}

If WinActive(“ahk_class Chrome_WidgetWin_1 ahk_exe chrome.exe”)
{
Clipboard := “[” . title . “](” . Clipboard . “)”
}
Return

Auto Linking Tool by @benperkins

@brimwats also provided 2 AHK scripts in Obsidian discord
https://discord.com/channels/686053708261228577/694233507500916796/798399078048202772

1st one is to remove PDF formatting (remove new line, remove double space,…)

; --------------Paste w/o formatting------------


^+v::
; Trim leading/trailing white space from empty lines 
Clipboard:=RegExReplace(Clipboard,"m)^[ \t]*$","`r`n")

; copied from http://ahkscript.org/docs/commands/StringReplace.htm
; Remove all blank lines from the text in a variable:
Loop
 {
   StringReplace, ClipBoard, ClipBoard, `r`n`r`n, --[ahkparagraphmarker]--, UseErrorLevel
   if ErrorLevel = 0  ; No more replacements needed.
     break
 }

;Replace all new lines with a space topreventjoinedwords 
StringReplace, ClipBoard, ClipBoard, `r`n, %A_Space%, All

; Remove all double spaces (useful for justified text)
Loop
 {
    StringReplace, ClipBoard, ClipBoard, %A_Space%%A_Space%, %A_Space%, UseErrorLevel
    if ErrorLevel = 0  ; No more replacements needed.
        break
 }

; re-create paragraphs again
StringReplace, ClipBoard, ClipBoard,--[ahkparagraphmarker]--,`r`n`r`n, All

; remove any leftover remaining leading spaces
Clipboard:=RegExReplace(Clipboard,"m)^[ \t]*")

Send ^v
Return

The 2nd script is auto formatting for highlighted text portion

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
/*
[script info]
version     = 2.5
description = wrap selected text in %symbols%
author      = davebrny
source      = https://gist.github.com/davebrny/088c48d6678617876b34f53571e92ee6

| hotkey          | hotstring |      result     |           notes          |
|-----------------|-----------|:---------------:|:------------------------:|
| alt + 2         | w2        | "text"          |                          |
| alt + '         | w'        | 'text'          | monospace text (MD)      |
| alt + `         | w`        | `text`          | in-line code block (MD)  |
| alt + 9         | w9        | (text)          |                          |
| alt + [         | w[        | [text]          |                          |
| alt + ]         | w]        | {text}          |                          |
| alt + ,         | w,        | <text>          |                          |
| alt + 5         | w5        | %text%          |                          |
| alt + .         | w.        | >>text<<        |                          |
| alt + 8         | w8        | *text*          | italic text (MD)         |
| alt + shift + 8 | w*        | **text**        | bold text (MD)           |
| alt + shift + # | w~        | ~~text~~        | strike through text (MD) |
| alt + -         | w-        | -text-          | strike through text (YT) |
| alt + shift + - | w_        | _text_          | italic text (YT)         |
| alt + k         | wkbd      | <kbd>text</kbd> | markdown key syntax      |
| alt + del       | wdel      | text            | del 2char either side    |
*/

sendMode input
return ; end of auto-execute
;---------------------------


!2::
::w2::
goTo, wrap_quote        ;   "text"

!'::
::w'::
goTo, wrap_apostrophe   ;   'text'

!`::
::w``::
goTo, wrap_grave        ;   `text`

!9::
::w9::
goTo, wrap_parenthesis  ;   (text)

![::
::w[[::
goTo, wrap_bracket      ;   [[text]]

!]::
::w]::
goTo, wrap_brace        ;   {text}

!,::
::w,::
goTo, wrap_angle        ;   <text>

!5::
::w5::
goTo, wrap_percent      ;   %text%

!.::
::w.::
goTo, wrap_2_angle      ;  >>text<<

!8::
::w8::
goTo, wrap_asterisk     ;   *text*

+!8::
::w*::
goTo, wrap_2_asterisk   ;  **text**

+!#::
::w~::
goTo, wrap_tilde        ;  ~~text~~

!-::
::w-::
goTo, wrap_hyphen       ;   -text-

+!-::
::w_::
goTo, wrap_underscore   ;   _text_

!k::
::wkbd::
goTo, wrap_kbd          ;   <kbd>text</kbd>

!del::
::wdel::
goTo, wrap_delete       ;   _text_  --->  text




;-----------------------




wrap_quote:
wrap_apostrophe:
wrap_grave:
wrap_parenthesis:
wrap_bracket:
wrap_brace:
wrap_angle:
wrap_percent:
wrap_2_angle:
wrap_asterisk:
wrap_2_asterisk:
wrap_tilde:
wrap_hyphen:
wrap_underscore:
wrap_kbd:
this_label := a_thisLabel
clipboard_text := get_clipboard()
for what, with in { "wrap_quote"       : """" clipboard_text """"
                  , "wrap_apostrophe"  :  "'" clipboard_text "'"
                  , "wrap_grave"       : "``" clipboard_text "``"
                  , "wrap_parenthesis" :  "(" clipboard_text ")"
                  , "wrap_bracket"     :  "[[" clipboard_text "]]"
                  , "wrap_brace"       :  "{" clipboard_text "}"
                  , "wrap_angle"       :  "<" clipboard_text ">"
                  , "wrap_percent"     :  "%" clipboard_text "%"
                  , "wrap_2_angle"     : ">>" clipboard_text "<<"
                  , "wrap_asterisk"    :  "*" clipboard_text "*"
                  , "wrap_2_asterisk"  : "**" clipboard_text "**"
                  , "wrap_tilde"       : "~~" clipboard_text "~~"
                  , "wrap_hyphen"      :  "-" clipboard_text "-"
                  , "wrap_underscore"  :  "_" clipboard_text "_"
                  , "wrap_kbd"         :  "<kbd>" clipboard_text "</kbd>" }
    stringReplace, this_label, this_label, % what, % with, all
new_text := this_label
goSub, send_wrap
return



wrap_delete:
clipboard_text := get_clipboard()
loop, 2
    {
    stringLeft, left_character, clipboard_text, 1
    stringRight, right_character, clipboard_text, 1
    if regExMatch(left_character, "[\Q'%*-_""~``([{><\E]")
        and if regExMatch(right_character, "[\Q'%*-_""~)``]}><\E]")  ; if  '%*-_"~`([{
        {
        stringTrimLeft, clipboard_text, clipboard_text, 1
        stringTrimRight, clipboard_text, clipboard_text, 1
        }
    else break
    }
new_text := clipboard_text
goSub, send_wrap
return



get_clipboard(){
    global
    if !inStr(a_thisHotkey, ":")    ; if hotkey was used
        {
        revert_clipboard := clipboardAll
        clipboard =
        send ^{c}
        clipWait, 0.3
        if clipboard is space
            clipboard =
        }

    return clipboard
}



send_wrap:
if !inStr(a_thisHotkey, ":") and if (clipboard = "")       ; if hotkey was used
     position := "{Left " round( strLen(new_text) / 2) "}" ; move cursor between symbols
else position := ""
clipboard := new_text
send % "^{v}" . position
sleep 150
clipboard := revert_clipboard
return
3 Likes

hello!

i realised that i spend a lot of time writing out long date formats because i’m pretty fond of how they look, so i decided to cobble together this AHK script to insert it for me using !!d because why the heck not? :robot:

it works beautifully as part of a larger script with other functions so feel free to just drop it right into default.ahk

; replaces '!!d' with today's ordinal date e.g. "Saturday the 13th of March, 2021"
:*:!!d::

day := ""
day .= findSuffix(A_DD)
SendInput %A_DDDD% the %day% of %A_MMMM%, %A_YYYY%
exit

findSuffix(d)
{
    d += 0
    if (d > 3 && d < 21)
        return d "th"
    switch Mod(d, 10)
    {
        case 1: d .= "st"
        case 2: d .= "nd"
        case 3: d .= "rd"
        default:
            d .= "th"
    }
    return d
}

feel free to improve it!

2 Likes

Hey, I’m having a tough time getting this script to execute. Should I run it in Obsidian?
Whenever I paste notes from icloud notes to Obsidian, there is always an extra space between lines. I’m trying to use your script to remove them, but it’s not working…

You need to install AHK then follow this instruction to create new script.
Then after you activate the script, you press ctrl+shift+V to paste the text with formatting removed.

Thanks for your quick reply. I’m familiar with the basics of AHK, though that info is definitely useful to a new user.
What I didn’t realize is that the script executes upon pasting, rather than after. Haha.

Still, the solution I’m looking for is to retain the formatting (i.e. If I have made a numbered list, I want those numbers to stay), but simply to remove the extra lines. I tried removing everything in your script except the second part (; Remove all blank lines from text…), but that didn’t work for me.

I guess I am still a noob when it comes to AHK, so could you help me refine the code a bit to work with what I need? Or could you give me some pointers?

Actually I don’t know much about coding
It took a while for me to google this script.
I made a small revision to delete single empty line:

^!Space::
	clipboard =
	Send, ^a
	Send, ^c
	ClipWait
	ClipBoard := RegExReplace(ClipBoard, "\R(?=\R{1,})") ;
	sleep 100
	Send, ^v
	return

Hope it help you.

Hi Guys,
I wanted to create a little AHK macro for myself, but I have a problem with the basic functionality - it seems I cannot copy selected text / paste to Obsidian.

The functionality I am after, which works OK in Notepad++ is here (select text and make it a link)

In obsidian, nothing happens - when inspecting, turns out that I cannot even copy or paste to Obsidian using AHK (yes, in Edit mode:) ). Regular copy/paste works OK.

The script I have is this

!+q::
Link := clipboard
Send, ^c
Description := clipboard
clipboard = %Description%
Send ^v
clipboard = %Link% ;restore
SoundBeep 100,400
return

There are problems with copy pasting with ahk I don’t know why it is that way. I use this code to make sure copying happen:

Clipboard := ""
Loop, {
    		SendInput, ^c
    		ClipWait, 0.5
    		If (ErrorLevel = 0)
        		Break
		}

Also , It’s kinda redundant. It plugin just does that:

1 Like

Hi,

I’m a really newbie in AHK and I need some help to active 2 hostrings for my dqily note’s template.

I created 2 hotstrings:

“::dd” for the note’s title:
:*:::d:: ;
#IfWinActive ahk_exe Obsidian.exe
FormatTime, CurrentDateTime, dddd dd MMMM yyyy ;
SendInput %CurrentDateTime%
return

And “::a” for the “breadcum trail” (Alfred Snippet for @mitzimbj's Daily Notes Breadcrumb Trail)

:*:::: a:: ;
#IfWinActive ahk_exe Obsidian.exe
yest = %a_now%
yest += -1, days
FormatTime, yest, %yest%, yyyyMMdd
today = %a_now%
today += +1, days
FormatTime, today, %today%, yyyyMMdd
SendInput [[%yest%|Yesterday]] - [[%today%|Tomorrow]]
return

I create a template in my obsidian with these 2 hotstrings for my daily note
Otherwise, when I create the note (with the template) the hotstrings are not been remplaced (I guess because i didn’t “write” them)

How can I fix it?
Thanks

Has anyone got autohotkey code highlighting in obsidian?
In the manual appears this link Prism, but when I use autohotkey it doesn’t work, with js (javascript) it works fine.

Can someone help me to make a script that wraps highlighted text into a tag? Now I have this (found on the web)

!=::WrapClipText("<span style='color:yellow'>", "</span>")
WrapClipText(Left,Right)
{
  ClipSaved := ClipboardAll
  Clipboard =
  send ^c
  Clipboard = %Left%%clipboard%%Right%
  send ^v
  Clipboard := ClipSaved
  ClipSaved = 
}

But I’d like to use this color blocks, so the highlighted text has to be wrapped into:

Screenshot_1

and I can’t get it to work. Any help is welcome, thanks!

I’m not an AHK hero, but I would do it this way:

!=::
ClipSaved := ClipboardAll
Clipboard =
send ^c
clipboard =
(
``````note-brown-background
%clipboard%
``` ```

)
send ^v
Clipboard := ClipSaved
ClipSaved =

Maybe there is a better way, but this works.

Important: in line 9 (under %clipboard%)`, the 6 backticks have to be written without a space in the middle. I had to insert the space because of the editor in this forum.

1 Like

Works like a charm, thanks for helping!