zsh-users
 help / color / mirror / code / Atom feed
* Outputting colored zsh prompts from an external script
@ 2013-03-24 19:23 seanh
  2013-03-24 21:48 ` Christian Neukirchen
  0 siblings, 1 reply; 8+ messages in thread
From: seanh @ 2013-03-24 19:23 UTC (permalink / raw)
  To: zsh-users

Hey,

I'm trying to write a Python script to handle my zsh prompts. The idea
is to call my Python script from my zshrc to define my PROMPT and
RPROMPT:

    PROMPT='$(zshprompt.py left)'
    RPROMPT='$(zshprompt.py right --last-exit-status=$?)'

(I also want to make it fall back on a default, pure-zsh prompt if
zshprompt.py returns a non-zero exist status, but that's to do later.)

The Python script then prints whatever it wants to stdout to form the
prompt and right prompt. The full code is here:

    https://gist.github.com/seanh/5233082

This all works fine, I've got my Python script ouptutting a nicely
truncated current working directory, name of the active virtualenv if
any, name of the current git branch if in a git repo, exit status of the
last command if non-zero, and user@host if using an ssh connection.

The problem comes when I try to introduce colors into the prompts. As
you can see from the Python code it's printing out ANSI escape sequences
to color the prompts, but this messes up the positioning of the right
prompt and cursor in zsh. Here's a screenshot showing the problem:

https://www.dropbox.com/s/4nqs7ceojmqqtmi/Screenshot%20from%202013-03-24%2020%3A01%3A21.png

The cursor has been pushed right along to left edge of the terminal
(instead of being after the left prompt as it should be), and the right
prompt seems to get pushed further and further to the left as more ANSI
escape codes come into the prompts.

Here's a screenshot of the same thing but with zshprompt.py's color()
function disabled, so you can see where everything's supposed to be:

https://www.dropbox.com/s/dg0p9741ip7zx1m/Screenshot%20from%202013-03-24%2020%3A00%3A35.png

I also tried getting zshprompt.py to print out zsh color codes like
%{$fg[red]%}FOO%{$reset_color%}, but zsh doesn't seem to interpret these
when they're printed by zshprompt.py, it just prints them out into the
prompts literally. I tried various zsh options with this, such as
setopt promptpercent and setopt promptsubst, and tried various other ways of
calling the Python script, such as within double-quotes or back-ticks
instead of single-quotes, or without any quotes at all. Nothing worked.

Any idea how I can do colour prompts from within my Python script?

Thanks


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Outputting colored zsh prompts from an external script
  2013-03-24 19:23 Outputting colored zsh prompts from an external script seanh
@ 2013-03-24 21:48 ` Christian Neukirchen
  2013-03-25 13:05   ` seanh
  0 siblings, 1 reply; 8+ messages in thread
From: Christian Neukirchen @ 2013-03-24 21:48 UTC (permalink / raw)
  To: zsh-users

seanh <snhmnd@gmail.com> writes:

> This all works fine, I've got my Python script ouptutting a nicely
> truncated current working directory

I ported this to zsh for fun:

fishpwd() {
  local maxlen=${1:-20} pwd
  local -a segs

  segs=("${(s:/:)${(D)PWD}}")

  for i in {1..$(($#segs-1))}; do
    pwd=${(j:/:)segs}
    (( $#pwd <= maxlen )) && break

    segs[$i]=${segs[$i][1]}
  done

  print $pwd
}

fishpwd 30
fishpwd 20
fishpwd 10

fishpwd

-- 
Christian Neukirchen  <chneukirchen@gmail.com>  http://chneukirchen.org


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Outputting colored zsh prompts from an external script
  2013-03-24 21:48 ` Christian Neukirchen
@ 2013-03-25 13:05   ` seanh
  2013-03-25 15:29     ` Bart Schaefer
  0 siblings, 1 reply; 8+ messages in thread
From: seanh @ 2013-03-25 13:05 UTC (permalink / raw)
  To: zsh-users

> I ported this to zsh for fun:
>
> fishpwd() {
>   local maxlen=${1:-20} pwd
>   local -a segs
>
>   segs=("${(s:/:)${(D)PWD}}")
>
>   for i in {1..$(($#segs-1))}; do
>     pwd=${(j:/:)segs}
>     (( $#pwd <= maxlen )) && break
>
>     segs[$i]=${segs[$i][1]}
>   done
>
>   print $pwd
> }

Yeah. I know that everything I want to do with zshprompt.py can be
done in pure zsh and I'm sure it can even be done elegantly in zsh.
The prompt I'm using right now, until I get zshprompt.py colors
working, is a pure zsh prompt that I implemented that has most of
zshprompt.py's features.

But the problem is that your zsh code is completely meaningless to me
because I don't know zsh. If I learned zsh well enough to do the
prompt I want, the in six months' time when I  want to change my
prompt or fix a bug I'll have forgotten all about it again because I
won't have used zsh scripting since. I write Python every day, so
being able to define zsh prompts by calling external programs (python
or otherwise) seems really empowering for letting more people hack
their zsh prompts.

So far this color issue is the only thing getting in my way...


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Outputting colored zsh prompts from an external script
  2013-03-25 13:05   ` seanh
@ 2013-03-25 15:29     ` Bart Schaefer
  2013-03-25 19:40       ` seanh
  0 siblings, 1 reply; 8+ messages in thread
From: Bart Schaefer @ 2013-03-25 15:29 UTC (permalink / raw)
  To: seanh; +Cc: zsh-users

On Mar 25,  2:05pm, seanh wrote:
}
} So far this color issue is the only thing getting in my way...

Your python script needs to either output %F{color} / %K{color} instead
of the raw ANSI sequences, or (might be easier) put %{ and %} around the
ANSI.  Both methods tell zsh that this output is "zero-width" on the
terminal, so it doesn't count those bytes when determing how much screen
space the prompt uses.  See also %G in the manual.

-- 
Barton E. Schaefer


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Outputting colored zsh prompts from an external script
  2013-03-25 15:29     ` Bart Schaefer
@ 2013-03-25 19:40       ` seanh
  2013-03-28 20:26         ` seanh
  0 siblings, 1 reply; 8+ messages in thread
From: seanh @ 2013-03-25 19:40 UTC (permalink / raw)
  To: zsh-users

> > So far this color issue is the only thing getting in my way...
> 
> Your python script needs to either output %F{color} / %K{color} instead
> of the raw ANSI sequences, or (might be easier) put %{ and %} around the
> ANSI.  Both methods tell zsh that this output is "zero-width" on the
> terminal, so it doesn't count those bytes when determing how much screen
> space the prompt uses.  See also %G in the manual.

That was exactly what I needed, thanks! Took all of two seconds to apply
and worked perfectly. I've updated the gist. The Python code could be
written more clearly, to make it explicit that the ANSI codes are
getting wrapped in zsh zero-width codes. Once I've given it some testing
and finished it off, I'll publish the script properly somewhere.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Outputting colored zsh prompts from an external script
  2013-03-25 19:40       ` seanh
@ 2013-03-28 20:26         ` seanh
  2013-03-28 21:14           ` TJ Luoma
  2013-03-29 15:07           ` Bart Schaefer
  0 siblings, 2 replies; 8+ messages in thread
From: seanh @ 2013-03-28 20:26 UTC (permalink / raw)
  To: zsh-users

> > > So far this color issue is the only thing getting in my way...
> > 
> > Your python script needs to either output %F{color} / %K{color} instead
> > of the raw ANSI sequences, or (might be easier) put %{ and %} around the
> > ANSI.  Both methods tell zsh that this output is "zero-width" on the
> > terminal, so it doesn't count those bytes when determing how much screen
> > space the prompt uses.  See also %G in the manual.
> 
> That was exactly what I needed, thanks! Took all of two seconds to apply
> and worked perfectly. I've updated the gist. The Python code could be
> written more clearly, to make it explicit that the ANSI codes are
> getting wrapped in zsh zero-width codes. Once I've given it some testing
> and finished it off, I'll publish the script properly somewhere.

Here's the "finished" version as I'm using it for now:

https://gist.github.com/seanh/5233082

Anyone know how I can make zsh call this script for PROMPT and RPROMPT,
but fall back on a simple pure-zsh prompt if trying to call the script
exits with non-zero? (Yes, my zsh-scripting skills really are that
limited.)

It does what I wanted from my prompt, with maybe a couple of minor
wrinkles that could be smoothed out. If I can get custom format options
working, it might be useful to others who want to design their own
prompts. I'm thinking it'd work something like this, for example to get
a zsh prompt with current working dir, virtualenv, git branch and last
exit status, you would put something like this in your zshrc:

    PROMPT='$(zshprompt.py --format "{cwd:green} {venv:blue} {git:yellow} {les:red,bold}> ")'

and zshprompt.py would do all the work to handle current working
directory truncation and git branch, virtualenv and non-zero exit status
detection, handle colours and bold etc and transform that (hopefully
simple) string specification into the much more complex string that zsh
needs for the prompt.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Outputting colored zsh prompts from an external script
  2013-03-28 20:26         ` seanh
@ 2013-03-28 21:14           ` TJ Luoma
  2013-03-29 15:07           ` Bart Schaefer
  1 sibling, 0 replies; 8+ messages in thread
From: TJ Luoma @ 2013-03-28 21:14 UTC (permalink / raw)
  To: seanh; +Cc: zsh-users

On Thu, Mar 28, 2013 at 4:26 PM, seanh <snhmnd@gmail.com> wrote:
> Anyone know how I can make zsh call this script for PROMPT and RPROMPT,
> but fall back on a simple pure-zsh prompt if trying to call the script
> exits with non-zero? (Yes, my zsh-scripting skills really are that
> limited.)
>
> It does what I wanted from my prompt, with maybe a couple of minor
> wrinkles that could be smoothed out. If I can get custom format options
> working, it might be useful to others who want to design their own
> prompts. I'm thinking it'd work something like this, for example to get
> a zsh prompt with current working dir, virtualenv, git branch and last
> exit status, you would put something like this in your zshrc:
>
>     PROMPT='$(zshprompt.py --format "{cwd:green} {venv:blue} {git:yellow} {les:red,bold}> ")'
>
> and zshprompt.py would do all the work to handle current working
> directory truncation and git branch, virtualenv and non-zero exit status
> detection, handle colours and bold etc and transform that (hopefully
> simple) string specification into the much more complex string that zsh
> needs for the prompt.

As someone who has never been able to figure out colors for zsh
prompts, I love this idea.

I don't know if there's a 'better' way to do this, but you could do it this way

FOO="$(a || b)"

if the exit code for 'a' != 0 then b will run.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Outputting colored zsh prompts from an external script
  2013-03-28 20:26         ` seanh
  2013-03-28 21:14           ` TJ Luoma
@ 2013-03-29 15:07           ` Bart Schaefer
  1 sibling, 0 replies; 8+ messages in thread
From: Bart Schaefer @ 2013-03-29 15:07 UTC (permalink / raw)
  To: seanh, zsh-users

On Mar 28,  9:26pm, seanh wrote:
}
} Anyone know how I can make zsh call this script for PROMPT and RPROMPT,
} but fall back on a simple pure-zsh prompt if trying to call the script
} exits with non-zero? (Yes, my zsh-scripting skills really are that
} limited.)

If exiting nonzero implies no output, you can do something like this:

PROMPT="${$(zshprompt.py left ...):-$PROMPT}"

where :- means that if the left side is empty, use the right side, so
the above effectively leaves the prompt unchanged if the script does
not output anything on stdout.

If you really want to test "exit nonzero" then you have to use two steps:

pyprompt="$(zshprompt.py left ...)" && PROMPT="$pyprompt"

or

if pyprompt="$(zshprompt.py left ...)"; then PROMPT="$pyprompt"; fi

or

[[ -x =zshprompt.py ]] && PROMPT="$(zshprompt.py left ...)"

etc.


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2013-03-29 15:07 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-24 19:23 Outputting colored zsh prompts from an external script seanh
2013-03-24 21:48 ` Christian Neukirchen
2013-03-25 13:05   ` seanh
2013-03-25 15:29     ` Bart Schaefer
2013-03-25 19:40       ` seanh
2013-03-28 20:26         ` seanh
2013-03-28 21:14           ` TJ Luoma
2013-03-29 15:07           ` Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).