You are not logged in.

#1 2008-09-24 16:05:30

dav7
Member
From: Australia
Registered: 2008-02-08
Posts: 674

Speed up slowish Bash PROMPT_COMMAND [FIXORED, fast nao]

Hey there. I recently got a little bored with my prompt and so decided to see if I could conjure up a new one.

A considerable amount of time later, I had a PROMPT_COMMAND configured... only issue is that it's, well, a bit slow. It takes 60 microseconds to generate the prompt string because of all the fun stuff I'm doing, and while you might be like "whoa... 60 microseconds", if you compare that with my last prompt, which didn't use PROMPT_COMMAND at all - just PS1 - and so used so little resources it'd be unmeasurable unless I used a timer that could handle nanoseconds, you might be able to get what I mean when I say there's a difference. Oh, then there's also the part where I have really fast vision...

So, I was wondering if this prompt (which really does look messier than the longest regex in the world) could be sped up at all.

For reference, this is my old prompt (the \016 and \017 only affects the '+' when at a text console, at which point it turns into a right-facing arrow - I developed the prompt while X was broken):

export PS1='\[\e]0;${PWD%/}/\007\e[1;30m\]${PWD%/}/ \[\e[32m\016\]+ \[\017\e[0m\]'

Now for my new prompt...

As one long, utterly unmanageable line:

export PROMPT_COMMAND='cwd=${PWD%/}; thisdir="$(echo $cwd | sed '\''s/.*\///'\'')"; dirparts="${cwd:0:$((${#cwd} - ${#thisdir}))}"; dirparts="$(echo ${dirparts%/} | sed '\''s/\//\\[\\e[0;33m\\]\/\\[\\e[32m\\]/g'\'')"; rc=${PWD%/}; rc=${rc:0:1}; PS1="\[\e]0;${cwd}/\007\e[1;36m\][\[\e[0;36m\]$(date "+%I:%M:%S %p")\[\e[1m\]] ${dirparts}\[\e[0;33m\]${rc}\[\e[1;34m\]${thisdir}\[\e[0;33m\]/\[\e[1;33m\] %\[\e[0m\] "'

Spaced out, for easy copying (can still be pasted into a terminal and will "run", note the quote characters at the beginning and end):

export PROMPT_COMMAND='
  cwd=${PWD%/};
  thisdir="$(echo $cwd | sed '\''s/.*\///'\'')";
  dirparts="${cwd:0:$((${#cwd} - ${#thisdir}))}";
  dirparts="$(echo ${dirparts%/} | sed '\''s/\//\\[\\e[0;33m\\]\/\\[\\e[32m\\]/g'\'')";
  rc=${PWD%/};
  rc=${rc:0:1};
  PS1="\[\e]0;${cwd}/\007\e[1;36m\][\[\e[0;36m\]$(date "+%I:%M:%S %p")\[\e[1m\]] ${dirparts}\[\e[0;33m\]${rc}\[\e[1;34m\]${thisdir}\[\e[0;33m\]/\[\e[1;33m\] %\[\e[0m\] "
'

I'm sure you'd understand if I told you that it took me a good half an hour to work out where to put all the \[s and \]s! lol

It looks nice-ish, but it isn't that cool with my not-so-speedy computer (it's 2.66GHz) which can be slow at some things - like this sad

Prompt requirements, in case you want to rewrite it from scratch (and I don't mind if you do, I sometimes do that sort of thing myself when dealing with other people's code, especially unmaintainable code):
- That the prompt is fast! tongue
- Slash characters are colored dark brown (0;33m)
- All directory components of the path except the current directory are colored dark green (0;32m)
- The current directory is colored bright blue (1;34m)
- A slash (/) is added before and after the path string, but methods are used to prevent "duplicate slash syndrome" if I'm in the root folder (ie "//"), and additionally these extra slashes are colored the dark brown (0;33m)
- There is a space, a '%' character, and a further space after the directory

Also, will zsh render a prompt like this one quickly? I just may switch over if it is. And as you can see, designing impossibly complex prompts isn't beyond me, so figuring out how zsh handles prompts shouldn't be too hard cool

-dav7

Last edited by dav7 (2008-09-25 03:18:09)


Windows was made for looking at success from a distance through a wall of oversimplicity. Linux removes the wall, so you can just walk up to success and make it your own.
--
Reinventing the wheel is fun. You get to redefine pi.

Offline

#2 2008-09-24 22:04:07

Profjim
Member
From: NYC
Registered: 2008-03-24
Posts: 658

Re: Speed up slowish Bash PROMPT_COMMAND [FIXORED, fast nao]

Those seds are what's slowing you down.

Why can't you replace the thisdir line with:

thisdir="${cwd##*/}"

and the second dirparts line with:

dirparts="${dirparts%/}"; dirparts="${dirparts//\//your_colored_replacement_stuff}"

Then bash can do everything inside bash, without starting any extra processes (except date, in the last line).

Offline

#3 2008-09-25 00:09:40

Profjim
Member
From: NYC
Registered: 2008-03-24
Posts: 658

Re: Speed up slowish Bash PROMPT_COMMAND [FIXORED, fast nao]

dav7 wrote:

Spaced out, for easy copying (can still be pasted into a terminal and will "run", note the quote characters at the beginning and end):

export PROMPT_COMMAND='
  cwd=${PWD%/};
  thisdir="$(echo $cwd | sed '\''s/.*\///'\'')";
  dirparts="${cwd:0:$((${#cwd} - ${#thisdir}))}";
  dirparts="$(echo ${dirparts%/} | sed '\''s/\//\\[\\e[0;33m\\]\/\\[\\e[32m\\]/g'\'')";
  rc=${PWD%/};
  rc=${rc:0:1};
  PS1="\[\e]0;${cwd}/\007\e[1;36m\][\[\e[0;36m\]$(date "+%I:%M:%S %p")\[\e[1m\]] ${dirparts}\[\e[0;33m\]${rc}\[\e[1;34m\]${thisdir}\[\e[0;33m\]/\[\e[1;33m\] %\[\e[0m\] "
'

Also, I think you might be able to replace the first dirparts line with:

dirparts="${cwd%$thisdir}"

Don't know whether that's going to make any perceptible speed difference though. Doubt it.

Offline

#4 2008-09-25 03:17:39

dav7
Member
From: Australia
Registered: 2008-02-08
Posts: 674

Re: Speed up slowish Bash PROMPT_COMMAND [FIXORED, fast nao]

Profjim wrote:

Don't know whether that's going to make any perceptible speed difference though. Doubt it.

Well, you might be surprised, but your changes have actually sped it up - on my system anyway.

My new PROMPT_COMMAND:

PROMPT_COMMAND='cwd=${PWD%/}; thisdir="${cwd##*/}"; dirparts="${cwd%$thisdir}"; dirparts="${dirparts%/}"; dirparts="${dirparts//\//\[\e[0;33m\]/\[\e[32m\]}"; rc=${PWD%/}; rc=${rc:0:1}; PS1="\[\e]0;${cwd}/\007\e[1;36m\][\[\e[0;36m\]$(date "+%I:%M:%S %p")\[\e[1m\]] ${dirparts}\[\e[0;33m\]${rc}\[\e[1;34m\]${thisdir}\[\e[0;33m\]/\[\e[1;33m\] %\[\e[0m\] "'

And spaced out, for easy {read,paste}ability:

PROMPT_COMMAND='
  cwd=${PWD%/};
  thisdir="${cwd##*/}";
  dirparts="${cwd%$thisdir}";
  dirparts="${dirparts%/}";
  dirparts="${dirparts//\//\[\e[0;33m\]/\[\e[32m\]}";
  rc=${PWD%/};
  rc=${rc:0:1};
  PS1="\[\e]0;${cwd}/\007\e[1;36m\][\[\e[0;36m\]$(date "+%I:%M:%S %p")\[\e[1m\]] ${dirparts}\[\e[0;33m\]${rc}\[\e[1;34m\]${thisdir}\[\e[0;33m\]/\[\e[1;33m\] %\[\e[0m\] "'
'

Some benchmarks; each measures the commands executed individually, then on one line.

Old prompt:

/Users/dav7/ + time cwd=${PWD%/};

real    0m0.000s
user    0m0.000s
sys    0m0.000s
/Users/dav7/ + time thisdir="$(echo $cwd | sed 's/.*\///')";

real    0m0.028s
user    0m0.010s
sys    0m0.000s
/Users/dav7/ + time dirparts="${cwd:0:$((${#cwd} - ${#thisdir}))}";

real    0m0.000s
user    0m0.000s
sys    0m0.000s
/Users/dav7/ + time dirparts="$(echo ${dirparts%/} | sed 's/\//\\[\\e[0;33m\\]\/\\[\\e[32m\\]/g')";

real    0m0.027s
user    0m0.007s
sys    0m0.007s
/Users/dav7/ + time rc=${PWD%/};

real    0m0.000s
user    0m0.000s
sys    0m0.000s
/Users/dav7/ + time rc=${rc:0:1};

real    0m0.000s
user    0m0.000s
sys    0m0.000s
/Users/dav7/ + time PS1="\[\e]0;${cwd}/\007\e[1;36m\][\[\e[0;36m\]$(date "+%I:%M:%S %p")\[\e[1m\]] ${dirparts}\[\e[0;33m\]${rc}\[\e[1;34m\]${thisdir}\[\e[0;33m\]/\[\e[1;33m\] %\[\e[0m\] "

real    0m0.014s
user    0m0.000s
sys    0m0.003s
[01:02:45 PM] /Users/dav7/ %
[01:02:45 PM] /Users/dav7/ % time (cwd=${PWD%/}; thisdir="$(echo $cwd | sed 's/.*\///')"; dirparts="${cwd:0:$((${#cwd} - ${#thisdir}))}"; dirparts="$(echo ${dirparts%/} | sed 's/\//\\[\\e[0;33m\\]\/\\[\\e[32m\\]/g')"; rc=${PWD%/}; rc=${rc:0:1}; PS1="\[\e]0;${cwd}/\007\e[1;36m\][\[\e[0;36m\]$(date "+%I:%M:%S %p")\[\e[1m\]] ${dirparts}\[\e[0;33m\]${rc}\[\e[1;34m\]${thisdir}\[\e[0;33m\]/\[\e[1;33m\] %\[\e[0m\] ")

real    0m0.025s
user    0m0.007s
sys    0m0.017s
[01:02:45 PM] /Users/dav7/ %

New prompt:

/Users/dav7/ + time cwd=${PWD%/};

real    0m0.000s
user    0m0.000s
sys    0m0.000s
/Users/dav7/ + time thisdir="${cwd##*/}";

real    0m0.000s
user    0m0.000s
sys    0m0.000s
/Users/dav7/ + time dirparts="${cwd%$thisdir}";

real    0m0.000s
user    0m0.000s
sys    0m0.000s
/Users/dav7/ + time dirparts="${dirparts%/}";

real    0m0.000s
user    0m0.000s
sys    0m0.000s
/Users/dav7/ + time dirparts="${dirparts//\//\[\e[0;33m\]/\[\e[32m\]}";

real    0m0.000s
user    0m0.000s
sys    0m0.000s
/Users/dav7/ + time rc=${PWD%/};

real    0m0.000s
user    0m0.000s
sys    0m0.000s
/Users/dav7/ + time rc=${rc:0:1};

real    0m0.000s
user    0m0.000s
sys    0m0.000s
/Users/dav7/ + time PS1="\[\e]0;${cwd}/\007\e[1;36m\][\[\e[0;36m\]$(date "+%I:%M:%S %p")\[\e[1m\]] ${dirparts}\[\e[0;33m\]${rc}\[\e[1;34m\]${thisdir}\[\e[0;33m\]/\[\e[1;33m\] %\[\e[0m\] "

real    0m0.014s
user    0m0.000s
sys    0m0.003s
[01:04:47 PM] /Users/dav7/ %
[01:04:47 PM] /Users/dav7/ % time (cwd=${PWD%/}; thisdir="${cwd##*/}"; dirparts="${cwd%$thisdir}"; dirparts="${dirparts%/}"; dirparts="${dirparts//\//\[\e[0;33m\]/\[\e[32m\]}"; rc=${PWD%/}; rc=${rc:0:1}; PS1="\[\e]0;${cwd}/\007\e[1;36m\][\[\e[0;36m\]$(date "+%I:%M:%S %p")\[\e[1m\]] ${dirparts}\[\e[0;33m\]${rc}\[\e[1;34m\]${thisdir}\[\e[0;33m\]/\[\e[1;33m\] %\[\e[0m\] ")

real    0m0.007s
user    0m0.000s
sys    0m0.007s
[01:04:47 PM] /Users/dav7/ %

A bit of trivia: when creating the new prompt, on the first try I didn't edit the appropriate changes in properly, and until I found myself examining it, I didn't realize this because it was so fast!

/Users/dav7/ + time (cwd=${PWD%/}; thisdir="${cwd##*/}"; dirparts="${cwd:0:$((${#cwd} - ${#thisdir}))}"; dirparts="${cwd%$thisdir}"; dirparts="${dirparts%/}"; dirparts="${dirparts//\//\[\e[0;33m\]/\[\e[32m\]}"; rc=${PWD%/}; rc=${rc:0:1}; PS1="\[\e]0;${cwd}/\007\e[1;36m\][\[\e[0;36m\]$(date "+%I:%M:%S %p")\[\e[1m\]] ${dirparts}\[\e[0;33m\]${rc}\[\e[1;34m\]${thisdir}\[\e[0;33m\]/\[\e[1;33m\] %\[\e[0m\] ")

real    0m0.004s
user    0m0.007s
sys    0m0.000s
/Users/dav7/ +

So, Profjim, thanks a heap! big_smile

-dav7

Last edited by dav7 (2008-09-25 03:18:44)


Windows was made for looking at success from a distance through a wall of oversimplicity. Linux removes the wall, so you can just walk up to success and make it your own.
--
Reinventing the wheel is fun. You get to redefine pi.

Offline

#5 2008-09-25 06:18:36

Profjim
Member
From: NYC
Registered: 2008-03-24
Posts: 658

Re: Speed up slowish Bash PROMPT_COMMAND [FIXORED, fast nao]

Glad it helped.

Offline

Board footer

Powered by FluxBB