---
feature_story: FS_92_75_93_01
feature_title: clean command line
feature_status: TODO
---

# Problem statement

Commands linked to `argrelay` can be part of a more complex command line (with sub-shells, `|`-pipe, loops, ...).

At the moment, `argrelay` can execute (`ServerAction.RelayLineArgs`) commands as part of such command lines,<br/>
but other operations may not work:
*   `Alt+Shift+Q`-search (`ServerAction.DescribeLineArgs`)
*   `Tab`-auto-completion (`ServerAction.ProposeArgValues`)

The reason is that Bash does not form clean command line (related sub-part of it) in those API calls.
In other words, `argrelay` cannot easily parse input as it receives the entire complex command line.

Even Bash itself warns in-line on such completion requests:

```
bash: compgen: warning: -C option may not work as you expect
```

# Current workaround

Construct `argrelay`-linked command as standalone, then put it into complex command line.

All `argrelay`-linked command will execute as expected in complex command lines (including shell-scripts),<br/>
because Bash will pass correct portion of that command line (related sub-part of it)<br/>
when that complex command line is executed (`ServerAction.RelayLineArgs`).

# Detailed examples

If `ARGRELAY_DEBUG` is defined, it is possible to observe what command line argrelay client receives:

```sh
export ARGRELAY_DEBUG="p"
```

Consider few cases:

1.  Command line with comment:

    ```sh
    lay some_arg # comment
    ```

2.  Command line with piped command:

    ```sh
    lay some_arg | cat
    ```

3.  Command line with sub-shell:

    ```sh
    echo $( lay some_arg )
    ```

4.  Command line in loops:

    ```sh
    for geo_region in amer apac emea ; do lay list service ; done
    ```

There is a difference how clean command line of unrelated chars is (depending on the action):

*   `ServerAction.DescribeLineArgs`

    This action has the dirtiest command line (Bash simply sends entire command line string):

    1.

    ```
    "lay some_arg # comment" cursor_cpos: 12 comp_type: 94
    ```

    2.

    ```
    "lay some_arg | cat" cursor_cpos: 12 comp_type: 94
    ```

    3.

    ```
    "echo $( lay some_arg )" cursor_cpos: 20 comp_type: 94
    ```

    4.

    No output (as the command line starts with `for` which is not linked to `argrelay).

*   `ServerAction.ProposeArgValues`

    This action is relatively safe from mis-interpretation, however, comments (after `#`) may still affect the results.

    1.

    ```
    "lay some_arg # comment" cursor_cpos: 12 comp_type: 33
    ```

    2.

    ```
    "lay some_arg " cursor_cpos: 12 comp_type: 33
    ```

    3.

    Bash does not invoke completion for command in sub-shell expression.

    4.

    Note that Bash does not pass empty line:

    ```
    "" cursor_cpos: 0 comp_type: 33
    ```

    Bash also warns:

    ```
    bash: compgen: warning: -C option may not work as you expect
    ```

*   `ServerAction.RelayLineArgs`

    This is the cleanest action.<br/>
    This is largely because the line is actually parsed by Bash first.<br/>
    Then, all args (passed by Bash) related to the command in question are simply concatenated on the client side.

    1.

    ```
    "lay some_arg" cursor_cpos: 12 comp_type: 42
    ```

    2.

    ```
    "lay some_arg" cursor_cpos: 12 comp_type: 42
    ```

    3.

    ```
    "lay some_arg" cursor_cpos: 12 comp_type: 42
    ```

    4.

    In all 3 iterations of the loop, Bash passes correct command lines:

    ```
    "lay list service amer" cursor_cpos: 21 comp_type: 42
    "lay list service apac" cursor_cpos: 21 comp_type: 42
    "lay list service emea" cursor_cpos: 21 comp_type: 42
    ```

The problem is that, depending on the extra chars, the interpretation outcome may become different.

# Bash version

The Bash version test results were obtained for:

```
bash --version
GNU bash, version 5.2.15(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
```

# Solution taken

Do nothing at the moment. Parsing Bash command line correctly (as Bash does) is a moving target<br/>
and requires relatively complex implementation (consider quotes for strings, nested sub-shell expressions, etc.).

Accept the limitation:
the functions should be used with clean command line by user for now
(no support from `argrelay` at the moment to process and clean up the command line).

# Possible way forward

Maybe `shlex` can be used for parsing command line (at least for stripping off quotes)?
https://docs.python.org/3/library/shlex.html

But this might be still difficult even for stripping off quotes
because we need to track the cursor position within the command line.

There are also some (relatively old though) disappointments about `shlex`:
https://www.reddit.com/r/learnpython/comments/42kq75/shlex_what_why/

# See also

A comment on the related issue:
https://github.com/argrelay/argrelay/issues/22#issuecomment-1873229478

