Skip to content

Instantly share code, notes, and snippets.

@davebrny
Last active February 18, 2024 12:29
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save davebrny/cd98cb10d4c944b065fda67b707cfd0b to your computer and use it in GitHub Desktop.
Save davebrny/cd98cb10d4c944b065fda67b707cfd0b to your computer and use it in GitHub Desktop.
✏️ (autohotkey) - wrap selected text in *symbols*
/*
[wrap list]
( = (TXT)
`[ = [TXT]
{ = {TXT}
< = <TXT>
> = >TXT<
a = /`*TXT*`/
h = <!-- TXT -->
k = <kbd>TXT</kbd>
m = ``` TXT ```
p = '''' TXT ''''
[settings]
select_after = true
input_limit = 1
delete_limit = 2
*/
#noEnv
#singleInstance, force
sendMode input
iniRead, select_after, % a_lineFile, settings, select_after
iniRead, input_limit, % a_lineFile, settings, input_limit
iniRead, delete_limit, % a_lineFile, settings, delete_limit
iniRead, ini_section, % a_lineFile, wrap list ; save wraps to variables
sort, ini_section, F long_lines_first_w
stringReplace, ini_section, ini_section, % "/``*", % "/*", all ; remove literals
stringReplace, ini_section, ini_section, % "*``/", % "*/", all
loop, parse, % ini_section, `n, `r
{
occurrence := (inStr(a_loopField, "=", , 1) = 1) ? ("L2") : ("") ; (if key name is the equals symbol, then L2)
stringGetPos, pos, a_loopField, =, % occurrence
stringMid, ini_value, a_loopField, pos + 2
stringMid, ini_key, a_loopField, pos, , L
ini_key := trim(ini_key)
ini_value := trim(ini_value)
if (ini_key = "```;") or (ini_key = "``[") ; remove literals
stringTrimLeft, ini_key, ini_key, 1
asc := asc(ini_key) ; convert key character to key number
%asc% := ini_value
wrap_list .= (wrap_list = "" ? "":"`n") . ini_value
}
ini_section := ""
return ; end of auto-execute ---------------------------------------------------
!w:: goSub, select_wrap
!+w::goSub, repeat_last_wrap
select_wrap:
toolTip, text wrap . . .
repeat_last_wrap:
selected := selected_text_w()
if (a_thisLabel = "select_wrap")
{
input, key, L%input_limit% T5, {delete}{d}{enter}{esc}
key := (key = "") ? strReplace(errorLevel, "EndKey:", "") : key
key := (key = "Escape") ? strReplace(key, "Escape", "") : key
asc := asc(key)
this_wrap := %asc% ; get wrap stored in key number
}
if (key = "delete") or (key = "d")
goSub, remove_wrap
else if (errorLevel != "Timeout") and if (key != "")
{
if (this_wrap)
split_wrap(this_wrap, l_wrap, r_wrap)
else
{
l_wrap := key
r_wrap := key
if (strLen(key) > 1)
{
reversed_string := ""
loop, parse, key
reversed_string := a_loopField . reversed_string
r_wrap := reversed_string
}
}
paste_text_w(l_wrap . selected . r_wrap)
}
toolTip, ; close
return
remove_wrap:
new_string := ""
loop, parse, % wrap_list, `n, `r ; figure out which wrap is being used
{
split_wrap(a_loopField, l_wrap, r_wrap)
if inStr(selected, l_wrap) and inStr(selected, r_wrap)
{
l_len := strLen(l_wrap) ; length of characters
r_len := strLen(r_wrap)
l_string := subStr(selected, 1, l_len) ; take same length from the string
r_string := subStr(selected, 1 - r_len, r_len)
if (l_wrap = l_string) and (r_wrap = r_string) ; match found on both sides
{
new_string := subStr(selected, l_len + 1, strLen(selected) - (l_len + r_len))
break
}
}
}
if (new_string = "") ; check for matching character on each side
{
tmp_string := selected
loop, % delete_limit
{
left_char := subStr(tmp_string, 1, 1)
right_char := subStr(tmp_string, 0, 1)
if (left_char = right_char) and regExMatch(left_char, "[^a-zA-Z0-9]") ; if match and not alphanumeric
tmp_string := subStr(tmp_string, 2, strLen(tmp_string) - 2) ; remove both sides
else break
}
if (tmp_string != selected) ; if something changed
new_string := tmp_string
}
if (new_string)
paste_text_w(new_string)
return
long_lines_first_w(line_a, line_b, offset) {
if strLen(line_b) != strLen(line_a)
return strLen(line_b) - strLen(line_a)
return -offset
}
selected_text_w() {
global save_clipboard
save_clipboard := clipboardAll
clipboard := ""
send ^{c}
clipWait, 0.1
if clipboard is not space
return clipboard
}
paste_text_w(string) {
global
clipboard := string
send ^{v}
sleep 200
if (selected = "")
send % "{left " strLen(r_wrap) "}" ; move caret between characters
else if (select_after = "true")
{
if (a_thisLabel = "remove_wrap") ; select whole string
send % "{left " strLen(string) "}+{right " strLen(string) "}"
else
{
stringGetPos, pos, string, % selected ; select original selection
send % "{left " (strLen(string) - pos) "}+{right " strLen(selected) "}"
}
}
sleep 300
clipboard := save_clipboard
}
split_wrap(wrap_text, byRef l_wrap, byRef r_wrap) {
stringGetPos, pos, wrap_text, TXT
stringMid, l_wrap, wrap_text, pos, , L
stringMid, r_wrap, wrap_text, pos + 4
}
/*
[script info]
version = 0.4
description = wrap selected text in %symbols%
author = davebrny
source = https://gist.github.com/davebrny/cd98cb10d4c944b065fda67b707cfd0b
*/
@davebrny
Copy link
Author

davebrny commented Jun 17, 2019

txt.wrap

wrap selected text in *symbols* using a two-stage hotkey

usage

  • highlight some text
  • press alt + w to activate wrap mode
  • then press any other key to have that character added to either side of the text
    • to remove characters from both sides, press delete or d

wrap mode will turn off itself after 5 seconds or can be turned off at any time by pressing the esc key

characters are only deleted on either side if they match and are not alphanumeric, or else if they are in the wrap list

if no text is selected then the wrap characters will be pasted and the cursor will be moved between them

 

settings

select_after

set to false if you dont want the text to be re-highlighted after its wrapped

input_limit

how many characters you want to add in one go. if its set to 2 or more and you are only adding 1 when in wrap mode then the enter key will need to be used to complete the wrap. if its set to 1 then the enter key isnt needed

alternatively, if select_after is enabled then you can get the same effect by doing two wraps one after another such as alt+w+" then alt+w+% to get "%TXT%"

delete_limit

if you know you will only ever want to delete 1 character on each side then set this to 1.
the default is set to 2 so things like **TXT** and ~~TXT~~ can be deleted in one go

custom wraps

new wraps can be added to the ini section at the top of the file.
a single character is used for the ini key and the ini value should have TXT in it with whatever characters you want on either side of it

if you are using ; or [ for the ini key then they need to have a literal ` character before them so they are not ignored by the script

if there is more than 1 of the same character in the list then the one the is lower down will be the one thats used. (upper and lower case letters will be seen as different characters though)

 

wrap examples

characters that normally require the shift key to be pressed

2  = "TXT"
5  = %TXT%
8  = *TXT*
9  = (TXT)
-  = _TXT_
`[ = {TXT}
#  = ~~TXT~~

autohotkey

c = /*TXT*/ 
h = ^!+{TXT}
t = trim(TXT)
s = inStr(TXT)

markdown

b = **TXT**
s = ~~TXT~~
B = ```TXT```
l = [TXT](url)
p = ![TXT](url)

html

i = <i>TXT</i>
b = <b>TXT</b>
1 = <h1>TXT</h1>
2 = <h2>TXT</h2>
c = <!-- TXT -->
k = <kbd>TXT</kbd>
i = <img src="TXT">
l = <a href="TXT">text</a>

phpBB forum BBCode

b = [b]TXT[/b]
i = [i]TXT[/i]
u = [u]TXT[/u]
q = [quote]TXT[/quote]
c = [code]TXT[/code]
l = [list]TXT[/list]
m =  [img]TXT[/img]
u =  [url]TXT[/url]
g = [gist]TXT[/gist]
@ = [mention]TXT[/mention]

 

related scripts:

txt.swap - interactively swap text at a certain character or word
txt.replace - interactively replace a character with another

@drwwww
Copy link

drwwww commented Feb 4, 2020

Brilliant, thank you!

@davebrny
Copy link
Author

davebrny commented Feb 4, 2020

Brilliant, thank you!

youre welcome!

@whlinaa
Copy link

whlinaa commented Mar 9, 2020

This script works a charm! Truly thankful that you share it with us! Thank you SO much!

@dummifiedme
Copy link

I don't exactly know how this works.
From trial and error I got myself to get working on the first set of symbols you provided. And there's an error. The shortcut listed for '{TXT}' is shift - ] but it rather works on 'shift - ['.

Also,
Can someplease tell me how to have my custom wrap?
I wanted a wrap for ANKI which goes like '{{c1::TXT}}'. Can someone tell me?

@davebrny
Copy link
Author

davebrny commented Sep 13, 2020

@dummifiedme just put this at the ini section at the top of the file, changing out 'a' for whatever hotkey you want to use. is that all you were having trouble with?

a = {{c1::TXT}}

ive fixed the wrap example to [ = {TXT} thanks

@yasma495
Copy link

I tried to add a custom wrap for « and » (Alt-0171 and Alt-0187)
Somehow I get B« and B»
My custome code looks like:
2 = «TXT»

@AF390
Copy link

AF390 commented Mar 14, 2021

Greetings, how do I modify this code, so that wrapping mode isnt deactivated after first use, but rather can be toggled?

@egochamberpie
Copy link

thanks for this. very helpful!

@mullimanko
Copy link

Thank you very much for this script. Do you intend to convert it to autohotey v2? I haven't the skills to do it on my own. Using AHK-v2-script-converter didn't work out.

@davebrny
Copy link
Author

Thank you very much for this script. Do you intend to convert it to autohotey v2? I haven't the skills to do it on my own. Using AHK-v2-script-converter didn't work out.

probably not! i switched to linux a few years back so im mostly using python now and dont even know what ahk v2 looks like. ive been getting good use out of copilot/bing chat lately though, maybe you might have more luck converting this script with that?

@mullimanko
Copy link

Ok thanks. You said you use python. Do you mean that you use python to create hotkeys (if yes which packages)? Or do you mean you use it just in general.

@davebrny
Copy link
Author

Ok thanks. You said you use python. Do you mean that you use python to create hotkeys (if yes which packages)? Or do you mean you use it just in general.

i actually still havnt got around to figuring out hotkeys in python. i know a few packages that will do that (keyboard, pyinput), but i am mostly using menus these days to run my scripts (instead of having a hotkey for each script), and since i only have 2 menus so i just setup those 2 hotkeys in the default linux/zorinOS settings GUI.

for basic key remapping im using kanata, which also lets you do QMK tap-hold type stuff (as in tapping space sends a normal space, but holding it turns it into a sort of a modifier key so you can put stuff on the home row like arrow keys or whatever)

for the menus im using fzf, and the iterfzf module to run fzf from within python scripts

@mullimanko
Copy link

Ok, thank you.

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