murex icon indicating copy to clipboard operation
murex copied to clipboard

UX: command-exists coloring & other beginner questions

Open Th0rgal opened this issue 6 months ago • 8 comments

Describe the query: Hi, I’m a new Murex user coming from zsh + powerlevel10k (+ zsh-syntax-highlighting).
In zsh, the first token turns green when it resolves (builtin or found in $PATH) and red when it does not. In Murex (with syntax-highlighting on), I don’t get this “command-exists” cue.

Separately, I sometimes see helpful inline/hint documentation while typing (looks like parsed docs). That hint shows for some commands (seems to be Murex builtins), but not for others like man (or external commands such as cursor). I’m unsure if I did anything wrong.

Steps to reproduce:

  1. Fresh Murex install (Homebrew on macOS) + Ghostty.
  2. Minimal config (see “Profile” below):
        config set shell syntax-highlighting on
        config set shell hint-text-enabled true
  1. Start a new shell and type:
    • help → inline hint appears.
    • man → no inline hint; first token not colored to indicate existence.
    • A nonsense command → no red “doesn’t exist” coloring.

Actual behaviour:

  • No green/red “command-exists” coloring for the first token.
  • Inline docs/hints appear for some commands (likely builtins) but not for external commands (e.g., man).

Expected behaviour:

  • While typing, color the first token green if it resolves to a builtin or an executable in $PATH, and red if it does not (parity with zsh-syntax-highlighting). Otherwise may be a hint when it's wrong.
  • Provide inline/hint docs consistently, ideally also for external commands when a man page or --help synopsis is available.

Additional runtime error: Intermittently, after a simple cd, I see:

        ❯ cd .config/
        Error in `tput` (/Users/thomas/.murex_modules/murex-module-starship/starship.mx 2,308):
              Command: tput cols
              Error: wait: no child processes

This appears to originate from the murex-module-starship (starship.mx) plugin calling tput. Not sure if this is a race with prompt rendering/events, but calling it out in case it’s related to the prompt/hints pipeline.

Profile / config:

        config set shell syntax-highlighting on
        config set shell hint-text-enabled true

        # Only enable when running under Ghostty
        if { $ENV.GHOSTTY_RESOURCES_DIR != "" } then {

            # Prompt start (A) + CWD (OSC 7)
            event onPrompt ghostty=before {
                exec sh -c 'printf "\033]133;A\007" >/dev/tty'
                exec hostname -> set HOST
                if { $HOST == "" } { set HOST localhost }
                # pass HOST and PWD as $1 and $2
                exec sh -c 'printf "\033]7;file://%s%s\007" "$1" "$2" >/dev/tty' _ $HOST $PWD
            }

            # Return pressed: prompt end (B) and command start (C)
            event onPrompt ghostty=return {
                exec sh -c 'printf "\033]133;B\007" >/dev/tty'
                exec sh -c 'printf "\033]133;C\007" >/dev/tty'
            }

            # Command finished (D;<exitcode>)
            event onPrompt ghostty=command-completion {
                -> set event
                if { $event.Interrupt.ExitNum != "" } {
                    # pass exit code as $1
                    exec sh -c 'printf "\033]133;D;%s\007" "$1" >/dev/tty' _ $event.Interrupt.ExitNum
                } else {
                    exec sh -c 'printf "\033]133;D;0\007" >/dev/tty'
                }
            }
        }

        export FAST_WORK_DIR=$HOME/.zsh/fsh/;
        export PATH=$PATH:~/.foundry/bin;
        export PATH=$PATH:~/.cargo/bin;
        export PATH=$PATH:~/.nargo/bin;
        export PATH=$PATH:~/.bitcoin/bin;
        export PATH=$PATH:~/.local/bin;
        export PATH=$PATH:~/.cairo/target/release;
        export PATH=$PATH:/opt/homebrew/bin;
        export PATH=$PATH:/usr/local/bin;
        export PATH=$PATH:~/.bun/bin;
        export PATH=$PATH:~/.starkli/bin;
        export PATH=$PATH:/opt/homebrew/opt/[email protected]/bin;
        export PATH=$PATH:~/.bun/install/global/node_modules/supabase/bin;
        export PATH=$HOME/.nix-profile/bin:/nix/var/nix/profiles/default/bin:$PATH
        export PATH=$HOME/.nix-profile/bin:$PATH

        alias rm="echo Use 'rip' instead of rm."
        alias ai=aichat -e

Environment:

  • Terminal: Ghostty (Apple Silicon)
  • OS: macOS (Tahoe 26.x)
  • Install: Homebrew
  • Modules: murex-module-starship (error above references starship.mx)
murex v7.0.2107 (develop)
GPL v2
2018-2025 Laurence Morgan

Documentation: Please rate your success with referring to the docs @ https://murex.rocks

  • [ ] I haven't read the docs / the solution should be more discoverable
  • [ ] I have read the docs but the content wasn't clear
  • [x] I have read the docs but this query was missing
  • [ ] I have read the docs and this query was answered but I'm still having problems

Questions / possible feature requests:

  • Is there a built-in way (or recommended plugin/theme) to enable command-exists coloring for the first token?
  • Are inline hints intentionally limited? Am I doing something wrong?
  • Any guidance on the tput cols → wait: no child processes error inside murex-module-starship?
Image Image

Th0rgal avatar Sep 20 '25 03:09 Th0rgal

Hi, welcome to Murex 👋

Hi, I’m a new Murex user coming from zsh + powerlevel10k (+ zsh-syntax-highlighting). In zsh, the first token turns green when it resolves (builtin or found in $PATH) and red when it does not. In Murex (with syntax-highlighting on), I don’t get this “command-exists” cue.

That used to be served by the hint text, eg

Image

I'm not sure why that's stopped working for builtins and commands. That'll be a regression bug, likely from around the time I was rewriting the hint text caching for performance. I will take a look at that.

I'm a little reluctant to colour the first token red because Murex is more expressive than Zsh, so expressions are valid commands eg

5 * 5              # outputs 10
foo = "bar"        # assign "bar" to a variable named "foo"
$variable          # outputs the value of the variable rather than executing the contents as a command
%[ foo, bar, baz ] # outputs JSON array: [ "foo", "bar", "baz" ]

Adding all these checks if the command line is an expression or a command statement would likely result in noticeable lag with the syntax highlighting (which already is a different and simplified parser to the main language parser). Plus the hint text provides much more detailed help about what a command actually calls than a simple red/green indicator would.

That all said, while I work on fixing this regression bug with hint text, I might figure out a performant way to apply the additional rules to the syntax highlighter too.

lmorg avatar Sep 21 '25 17:09 lmorg

Intermittently, after a simple cd, I see:

   ❯ cd .config/
   Error in `tput` (/Users/thomas/.murex_modules/murex-module-starship/starship.mx 2,308):
         Command: tput cols
         Error: wait: no child processes

This appears to originate from the murex-module-starship (starship.mx) plugin calling tput. Not sure if this is a race with prompt rendering/events, but calling it out in case it’s related to the prompt/hints pipeline.

Yeah that's definitely Starship. I don't use Starship personally, but what's likely happening is the background process that's being called by Starship is being cancelled before Starship has finished execution (eg if you're super quick at changing directory).

tput, as I'm sure you're aware, is a just a POSIX command for determining terminal capabilities. eg does the terminal support SGR ANSI escape sequences for colour. In this instance, it's just checking how wide the terminal is.

I can take a look at the Starship module, but it's not published by me so I might not be able to fix this specific bug.

lmorg avatar Sep 21 '25 17:09 lmorg

Looking at your code, it's already pretty good for someone new to the shell. I'm impressed you've gotten the hang of the events subsystems. I wasn't sure how well I'd documented that.

A couple of potential changes, if you fancy it:


Alias

alias rm="echo Use 'rip' instead of rm."

Alias doesn't need to be quoted. So you could write that something like:

alias rm=err "Use 'rip' instead of rm."

The Ghostty codes could also be simplified, eg

exec sh -c 'printf "\033]133;A\007" >/dev/tty'

could be written as

out "{ECS}]133;A{BELL}" |> /dev/tty

https://murex.rocks/user-guide/ansi.html#unsupported-constants


PATH

You might find this syntax easier to work with. You need := token because that forces a data-type conversion from JSON to whatever datatype the var originally held (in this case, paths)

ENV.PATH := %[
    ~/.nix-profile/bin
    ~/.nix-profile/bin:/nix/var/nix/profiles/default/bin
    @PATH
    ~/.foundry/bin
    ~/.cargo/bin
    ~/.nargo/bin
    ~/.bitcoin/bin
    ~/.local/bin
    ~/.cairo/target/release
    /opt/homebrew/bin
    /usr/local/bin
    ~/.bun/bin
    ~/.starkli/bin
    /opt/homebrew/opt/[email protected]/bin
    ~/.bun/install/global/node_modules/supabase/bin
]

Which you mind find a little more readable and easier to maintain than a long list of export keywords. But this is purely a matter of personal preference.

lmorg avatar Sep 21 '25 18:09 lmorg

Thank you very much ! I updated my config with your trick and I have now removed starship, but I keep getting (though less often it seems) this kind of bug:

workspace » cd Adversarial-Paraphrasing/
Error in `hostname` (/Users/thomas/.murex_profile 3,466):
      Command: exec hostname
      Error: wait: no child processes

or after a cat:

Error in `hostname` (/Users/thomas/.murex_profile 3,466):
      Command: exec hostname
      Error: wait: no child processes

Indeed fixing the hint text sounds much better than coloring the first token.

Th0rgal avatar Sep 22 '25 08:09 Th0rgal

Looks like there is an underlying problem there.

Thanks for the report. I'll investigate this further tonight

lmorg avatar Sep 22 '25 08:09 lmorg

I think the issue is just the executable finishing before Murex starts waiting for the executable to finish.

The OS syscall returns no child processes when the wait syscall sends a pid which isn't valid. The only place I'm calling wait is when forking executables and the examples you've given are all short lived programs.

In this context, the error can be discarded because we don't need to wait for something that's already finished. So I'll add that in and we can see if the error persists afterwards.

lmorg avatar Sep 22 '25 18:09 lmorg

Awesome, I'm looking forward to trying it!

Th0rgal avatar Sep 23 '25 00:09 Th0rgal

Found the issue for the application name not appearing in the hint text.

I've pushed an update to develop branch that fixes the above

lmorg avatar Sep 25 '25 09:09 lmorg