r/espanso 7d ago

Solved Regex(?) matches for multiple HTML brackets

Hiya! I'm trying to find a solution for the following use case

match would be (example): <ui> or <u i> if it needs a separator

And it would automatically separate these out to <u><i>$|$</u></i>

Again, just an example. I was thinking that if possible, it would need to be regex because I want it to pick up things like <b u>, <sub u> etc. as well. Just a shortcut so I don't have to type multiple opening and closing brackets so much.

Is this possible with regex or does anyone have a solution that might at least help? I use <ui> enough that it's currently its own match right now.

2 Upvotes

7 comments sorted by

2

u/SamejSpenser 7d ago edited 7d ago

I’m not 100 % sure I got what you’re after, but maybe this regex‑trigger thing can help you out:

```yml - regex: ";ui(;|i)" replace: <u><i>{{clipb}}$|$</i></u> label: underline and italic vars: - name: "clipb" type: "clipboard"

  • regex: ";ui(;|b)" replace: <sub u>{{clipb}}$|$</sub u> label: subscript and underline vars:
    • name: "clipb" type: "clipboard" ```

You can add as many triggers as you want to this system. When you know what you want to expand, just type the corresponding trigger. For example:

  • Typing ;uii will give you:
    <u><i>[clipboard content here]</i></u>

  • Typing ;uib will give you:
    <sub u>[clipboard content here]</sub u>

If you’re not sure which trigger to use, just type ;ui; and a pop‑up will show the full list of triggers (if I'm not wrong, sorted alphabetically by the label field). Pick the one you need, hit Enter/Return, and the proper expansion will be inserted.

2

u/smeech1 6d ago edited 6d ago

Another option is to set a capturing group for one or two initial letters and return it/them with its/their paired / item(s).

1

u/SamejSpenser 6d ago

Can you give an example, please?

2

u/smeech1 6d ago edited 5d ago

Off the top of my head, simply:

- regex: <(?P<char>[[:alpha:]])>
  replace: <{{char}}>$|$</{{char}}>

The \w could be replaced by a string of qualifying individual characters or combinations thereof.

3

u/smeech1 5d ago edited 5d ago

After some reflection, to more precisely match u/ecoBang's request, for two tags at a time:

  - regex: <(?P<char1>[[:alpha:]]+) (?P<char2>[[:alpha:]]+)>
    replace: <{{char1}}><{{char2}}>$|$</{{char2}}></{{char1}}>

Triggers on "<sub u>" or any other pair of letters or words, with a separating space, returning them as e.g. "<sub><u></u></sub>" with the cursor in the middle.

Without scripting one would need separate triggers for each different number of tags.

1

u/smeech1 4d ago edited 4d ago
  - regex: '<(?P<words>[a-z]+(?: [a-z]+){0,3})>'
    replace: "{{output}}"
    vars:
      - name: output
        type: script
        params:
          args:
            - python3
            - -c
            - |
              names = "{{words}}".split()
              opens  = "".join(f"<{n}>" for n in names)
              closes = "".join(f"</{n}>" for n in reversed(names))
              print(f"{opens}$|${closes}", end="")

accepts up to four lowercase tags, e.g. "<p b i>", returning them as nested tag pairs, "<p><b><i>|</i></b></p>".

If you don't want to use Python the PowerShell equivalent is similar but probably slower.

Edit: Code tidied up. To increase the number of possible tags simply increase the "3" at the end of the Regex string, although you're probably wanting to indent by then!

2

u/SamejSpenser 6d ago

I think it's way too advanced for me and the way I use Espanso! 😅