Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Unescaping certain regex options. #177

Merged
merged 4 commits into from
Dec 3, 2023
Merged

fix: Unescaping certain regex options. #177

merged 4 commits into from
Dec 3, 2023

Conversation

yjyao
Copy link
Contributor

@yjyao yjyao commented Dec 3, 2023

Many regexes contain escaped characters
like \s or \w.
tmux-fastcopy queries the tmux environment
for regex overwrites.
Specifically,
it uses the tmux show-options -g command.
The output in turn escapes the backward slashes,
turning \s into \\s.
To correctly parse the regex overwrites,
tmux-fastcopy needs to unescape these backward slashes too.

The tmux show-options -g command prints values in three forms:

  • Unquoted for simple, unspaced values:

    $ tmux set @myopt hey ; tmux show @myopt
    @myopt hey
  • Single-quoted for simple, double-quoted values:

    $ tmux set @myopt hey\"world ; tmux show @myopt
    @myopt 'hey"world'
  • Double-quoted for other values:

    $ tmux set @myopt hey\  ; tmux show @myopt
    @myopt "hey "

Note that the output escapes backward slashes
in all three forms:

$ tmux set @myopt '\hey' ; tmux show @myopt
@myopt \\hey

$ tmux set @myopt '\"hey' ; tmux show @myopt
@myopt '\\"hey'

$ tmux set @myopt '\ hey' ; tmux show @myopt
@myopt "\\ hey"

For many regexes,
tmux would print the value unquoted.
For example, the path regex built-in to tmux-fastcopy is like this:

$ tmux set-option @myopt '(\b([\w.-]+|~)?(/[\w.-]+)+\b)' ; tmux show @myopt
@myopt (\\b([\\w.-]+|~)?(/[\\w.-]+)+\\b)

Currently,
tmux-fastcopy relies on strconv.Unquote
in the tmuxopt.Loader.ReadValue function
to unescape the backslashes.
However,
a caveat is that strconv.Unquote only performs
if the given string is quoted.
As a result,
tmux-fastcopy never unescapes the regex from the last paragraph, and would fail to match it.

This commit fixes the problem
by manually double-quoting unquoted strings,
forcing strconv.Unquote to unescape them.

(The above results were tested with tmux 3.3a in bash 5.2.15(1)-release.)


TIP: Before this PR is merged (if ever),
a workaround is to force tmux to double-quote the value
for example by prefixing your regex with a "{0}
which matches nothing.

Many regexes contain escaped characters
like `\s` or `\w`.
`tmux-fastcopy` queries the tmux environment
for regex overwrites.
Specifically,
it uses the `tmux show-options -g` command.
The output in turn escapes the backward slashes,
turning `\s` into `\\s`.
To correctly parse the regex overwrites,
`tmux-fastcopy` needs to unescape these backward slashes too.

The `tmux show-options -g` command prints values in three forms:

-   Unquoted for simple, unspaced values:

    ```shell
    $ tmux set @myopt hey ; tmux show @myopt
    @myopt hey
    ```

-   Single-quoted for simple, double-quoted values:

    ```shell
    $ tmux set @myopt hey\"world ; tmux show @myopt
    @myopt 'hey"world'
    ```

-   Double-quoted for other values:

    ```shell
    $ tmux set @myopt hey\  ; tmux show @myopt
    @myopt "hey "
    ```

Note that the output escapes backward slashes
in all three forms:

```shell
$ tmux set @myopt '\hey' ; tmux show @myopt
@myopt \\hey

$ tmux set @myopt '\"hey' ; tmux show @myopt
@myopt '\\"hey'

$ tmux set @myopt '\ hey' ; tmux show @myopt
@myopt "\\ hey"
```

For many regexes,
tmux would print the value unquoted.
For example, the path regex built-in to `tmux-fastcopy` is like this:

```shell
$ tmux set-option @myopt '(\b([\w.-]+|~)?(/[\w.-]+)+\b)' ; tmux show @myopt
@myopt (\\b([\\w.-]+|~)?(/[\\w.-]+)+\\b)
```

Currently,
`tmux-fastcopy` relies on `strconv.Unquote`
in the `tmuxopt.Loader.ReadValue` function
to unescape the backslashes.
However,
a caveat is that `strconv.Unquote` only performs
if the given string is quoted.
As a result,
`tmux-fastcopy` never unescapes the regex from the last paragraph,
and would fail to match it.

This commit fixes the problem
by manually double-quoting unquoted strings,
forcing `strconv.Unquote` to unescape them.
Adds an integration test to verify the unquoting behavior
against a running copy of tmux.

This required exporting the readValue function
so that we can access it from the integration test package.
@abhinav
Copy link
Owner

abhinav commented Dec 3, 2023

This is excellent! Thanks for the fix, and the thorough explanation. Much appreciated!
I added a small integration test to verify this behavior with running copies of tmux, and that appears to be green for all versions of tmux we're testing against.

@abhinav abhinav merged commit 3f789aa into abhinav:main Dec 3, 2023
11 checks passed
abhinav added a commit that referenced this pull request Dec 3, 2023
Release a new version with the following fixes:

- #177
@abhinav abhinav mentioned this pull request Dec 3, 2023
abhinav added a commit that referenced this pull request Dec 3, 2023
Release a new version with the following fixes:

- #177
@abhinav
Copy link
Owner

abhinav commented Dec 3, 2023

Released in 0.14.1. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants