NetBSD-Users archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: How do you set $PS1 on /bin/ksh



    Date:        Fri, 24 Jan 2020 13:19:39 +0000
    From:        Ottavio Caruso <ottavio2006-usenet2012%yahoo.com@localhost>
    Message-ID:  <CAEJNuHymoGWLryUFeLYF_AH-qfed1ymvayhByFsbV+-9WXoP=Q%mail.gmail.com@localhost>

  | How do you set the prompt in ksh?

The same way one would set it in any other Bourne shell (more or less)
compatible shell, PS1='whatever'

  | The man page doesn't seem to help.

It looks reasonably accurate to me.

  | OpenBSD ksh has a different manpage. Compare:
  | https://man.openbsd.org/ksh.1#PS1
  | and
  | https://netbsd.gw.com/cgi-bin/man-cgi?ksh

There are a zillion different things called ksh, I'm not
sure which version OpenBSD have as ksh (I believe they use
mksh as /bin/sh so that variety of ksh might be used for both).

  | For example:
  | PS1="\u@\h:\w\$ "

backslash escapes in PS1 are an abomination (someone added them in
some version of ksh to attempt to be more csh compatible, but why
anyone would want that restricted nonsense when there are better
ways is beyond me).

  | is not expanded.

It is, I expect (I'm not a ksh user so I can't guarantee it) but
there are no appropriate expansion requests in there, as the man
page says:

  PS1    PS1 is the primary prompt for interactive shells.  Parameter,
         command and arithmetic substitutions are performed, and ! is
         replaced with the current command number (see fc command below).

There are no parameter, command, or arithmetic substitutions in that PS1
string, and no ! characters (another gross hack that was in the original ksh,
also for csh compat reasons I believe) either.

You can achieve most of what that expansion achieves using command or
variable expansions (\u is $(id -un) \h is $(hostname -s) \w is trickier,
as it hides $HOME with ~, but:

$( X=${PWD#${HOME}}; case "$X" in "${PWD}") echo "$X";; *) echo "~$X";; esac )

should do it.   Last \$ turns into $C after
	if [ $( id -u ) = 0 ]; then C=#; else C=$; fi
(obviously use anything you prefer instead of 'C').   Other than the PWD
expression, all of those can be expanded at definition time (unless you
anticipate the hostname randomly changing) so defined in "" but the PWD
evaluation needs to be at execution time so defined in '', so overall
you'd end up with something like

if [ $( id -u ) = 0 ]; then C=#; else C=$; fi
PS1="$(id -un)@$(hostname -s):"'$(
	X=${PWD#${HOME}};
	case "$X" in
	("${PWD}") echo "$X";;
	(*) echo "~$X";;
	esac
)'"$C "

That actually works in ksh, as well as in /bin/sh bash mksh ksh93
(even yash and dash)...   (Don't try it without the, what should be
optional, leading '(' around the case patterns, while no other shell
objects, our /bin/ksh does ... it is ancient and full of odd bugs).

I'd suggest using /bin/sh instead (and if you do that, and need any
command expansions actually performed at run time in PS1 (or PSanything)
then "set -o promptcmds" first).

For this kind of thing though, an alternative I prefer is to have what
you want to be printed as the directory part in a variable, and then
update that variable whenever you have successfully completed a cd
command, something like

	cd() {
		command cd "$@" &&
			CDIR=$( .... )
	}

and then just use ${CDIR} in the prompt, though I prefer to have the
cd function embed it in my window's title bar instead when I am using
windows in X (most of the time) so the prompt string stays short.

kre

ps: the reason this way is better than \ escapes is that it allows you to
put anything you want in PS1 not just the half dozen things the csh
authors decided you might want to stick in there.  /bin/sh has a few
special variables that make building dynamic prompts easier, like PSc
is preset to be the # or $ character, no need for doing it yourself.



Home | Main Index | Thread Index | Old Index