8

I'm using zsh in OS X Terminal.app and for quite a while, I've been longing for a way to jump back and forth between prev/next prompts in the terminal's output.

One convenience with this would be to be able to review (and track errors at) the end of each command's output; eg. when you building stuff from source with ./configure; make; make install. Note: I'm obviously not referring to jumping back and forth in the command-history, but for a way to take a peek at the endings of each command's output.

Has anyone heard of such functionality in the *nix (preferrably also Mac) world? Would it require some sort of OS-centric Terminal plugin, or can it be programmatically done via a shell script which can be tied to a keyboard shortcut? Maybe I'm the only one thinking about this? :)

7
  • Do you have control over the command sequence that is being run? do you just want a pause? would you like it to prompt you to continue? Commented Oct 30, 2010 at 23:23
  • Here's an example scenario: Let's say I want to compile and install some program (using standard ./configure && make && make install procedure) and after the make command, I run into some errors. Now, the way I understand it (I may be completely wrong), the crucial error, causing the make command to fail, usually shows up in the last line(s) in the output, no? Anyway, at this point, I might do something like `cat INSTALL' to read the INSTALL document to check if there's something I've missed. (Due to comment characters restriction I'm continuing in my next comment.)
    – Henrik
    Commented Oct 31, 2010 at 0:01
  • NOW, if I want to go back to see what the error was that caused my initial make command to fail, I now have to manually scroll up to that position again, since my `cat INSTALL' printed a ton of text after it. I don't know if this scenario is the most elucidative – but there are many other situations where I wish I could just "jump" back to previous prompt lines and check up on previous command output; whether it was a simple ls command, make, git status, or whatever it was – swapping positions in the window by means of using prompts as "bookmark" positions seems an interesting idea to me.
    – Henrik
    Commented Oct 31, 2010 at 0:08
  • 1
    @hced no, errors can be anywhere in the output, the best way to find errors post is to redirect stederr to a file. Commented Oct 31, 2010 at 6:14
  • 1
    @hced I don't do redirection often, and don't feel like looking it up, somewhere on here someone has posted on redirection. but that looks right. except... why are you running make with sudo you should never (have to) compile as root. only make install could require root. Commented Nov 3, 2010 at 11:38

5 Answers 5

4

I've never heard of such a feature with typical shells (zsh, fish or otherwise) in typical terminal emulators. Once you've pressed Enter at a prompt, that command line only exists as a history entry as far as the shell is concerned, and as a bunch of displayed characters (indistinguishable from command output) as far as the terminal emulator is concerned.

On the other hand, the kind of navigation you ask for is available as a matter of course in shells run in an Emacs buffer, with M-x shell if you want your usual shell and Emacs's command line edition or M-x eshell if you want a shell built into Emacs.

4
  • 1
    I'd vote you up if I could, albeit my current reputation doesn't allow me to. Thanks for you interesting info. Dumb question probably, but how do you perform such navigation in Emacs' shell? This also makes me curious if it holds true in Vim as well (which is the editor I'm settled for learning), using :shell (in which case my previous dumb question also applies to Vim; how do you perform the "jump between prompts" in Vim's shell).
    – Henrik
    Commented Nov 3, 2010 at 11:51
  • 3
    @hced: In Emacs, you get normal cursor navigation, plus a few specific commands like C-c C-p and C-c C-n to navigate to the previous/next prompt. Vim doesn't have any similar feature: :shell just starts a shell that interacts directly with the terminal Vim is running in (and you can't interact with Vim until the shell exits). Commented Nov 3, 2010 at 18:51
  • +1 I didn't know about C-c C-p. Thanks!
    – Mikel
    Commented Jan 24, 2011 at 22:25
  • In eshell, there is even such a command as eshell-show-output, which seems to do even more closely what hced is after when asking this question. Commented Mar 20, 2011 at 18:59
2

In eshell in Emacs, there is command (not yet mentioned here in other answers) that seems to tackle the task you are implicitly wondering about when asking your question -- eshell-show-output; its description (C-h feshell-show-output):

It is bound to C-c C-r, C-M-l.

(eshell-show-output &optional arg)

Display start of this batch of interpreter output at top of window. Sets mark to the value of point when this command is run. With a prefix argument, narrows region to last command output.

The narrowing effect (with a prefix argument, i.e., C-u C-c C-r) could be also interesting to you given your task.

1
  • Thanks for the tip, will try this if I start using Emacs. (I'm more into Vim these days. If there's a ditto technique for Vim like the one you described above, I'd be happy to hear it.)
    – Henrik
    Commented Mar 21, 2011 at 12:12
1

One answer to your question is to use emacs with M-x eshell. This gives you a reasonably full shell functionality inside of emacs. Taking quick peeks at files can obviously be done by opening them in the editor, but more importantly you can use its search functionality to search back through the buffer for any earlier output (or any earlier prompts).

Another answer is to use screen, I believe this also has a search functionality of the history, but it has been too long since I used it to remember what the key-combos are.

1
1

To expand on xenoterracide's comment...

Rather than run make, I put this in my .bashrc

# make with an automatic log and pager
m()
{
    command make "$@" 2>&1 1>&- 1>make.log | tee -a make.log
}

then run m instead of make.

This puts all output to make.log, but only prints errors on the console.

That way you don't have tonnes of output on the screen, can easily see errors, and can read make.log to diagnose any problems if it failed.

0

Not sure if this should be an answer, but since I'm posting an image I guess it will work.

You can make your bash prompt look different so that it's easily spotted, or use zsh and make your prompt look something like this.

alt text

I took my prompt from someplace online, I forget where. And I combined it with another zshrc file I found elsewhere. I'll just paste the whole thing here. The prompt is all contained in the bottom if you just awnt to take that.

#------------------------------
# History stuff
#------------------------------
HISTFILE=~/.histfile
HISTSIZE=1000
SAVEHIST=1000

#------------------------------
# Variables
#------------------------------
export EDITOR="vim"
export PAGER="vimpager"
export PATH="${PATH}:${HOME}/bin"
export PATH="${PATH}:${HOME}/.android-sdk-linux_x86/tools"
export PATH="${PATH}:${HOME}/Dropbox/bin"
#-----------------------------
# Dircolors
#-----------------------------
#LS_COLORS='rs=0:di=01;34:ln=01;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:tw=30;42:ow=34;42:st=37;44:ex=01;32:';
#export LS_COLORS


LS_COLORS='di=34;01:fi=0:ln=96;1:pi=36;1:so=01;31;1:bd=5:cd=5:or=01;31:mi=0:ex=01;93:*.so*=93:*.doc=01;33:*.docx=01;33:*.xls=01;33:*.xlsx=01;33:*.pdf=01;33:*.odt=01;33:*.torrent=91:*.bin=33:*.sh=33:*.run=33:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:'
export LS_COLORS



#------------------------------
# Keybindings
#------------------------------
bindkey -e
typeset -g -A key
#bindkey '\e[3~' delete-char
bindkey '\e[1~' beginning-of-line
bindkey '\e[4~' end-of-line
#bindkey '\e[2~' overwrite-mode
bindkey '^?' backward-delete-char
bindkey '^[[1~' beginning-of-line
bindkey '^[[5~' up-line-or-history
bindkey '^[[3~' delete-char
bindkey '^[[4~' end-of-line
bindkey '^[[6~' down-line-or-history
bindkey '^[[A' up-line-or-search
bindkey '^[[D' backward-char
bindkey '^[[B' down-line-or-search
bindkey '^[[C' forward-char 
# for rxvt
bindkey "\e[8~" end-of-line
bindkey "\e[7~" beginning-of-line
# for gnome-terminal
bindkey "\eOH" beginning-of-line
bindkey "\eOF" end-of-line

#------------------------------
# Alias stuff
#------------------------------
alias ls="ls --color -F"
alias ll='ls -lAgh --group-directories-first --color'
alias saptget="sudo apt-get "



#------------------------------
# Comp stuff
#------------------------------
zmodload zsh/complist 
autoload -Uz compinit
compinit
zstyle :compinstall filename '${HOME}/.zshrc'

#- buggy
zstyle ':completion:*:descriptions' format '%U%B%d%b%u'
zstyle ':completion:*:warnings' format '%BSorry, no matches for: %d%b'
#-/buggy

zstyle ':completion:*:pacman:*' force-list always
zstyle ':completion:*:*:pacman:*' menu yes select

zstyle ':completion:*:default' list-colors ${(s.:.)LS_COLORS}

zstyle ':completion:*:*:kill:*' menu yes select
zstyle ':completion:*:kill:*'   force-list always

zstyle ':completion:*:*:killall:*' menu yes select
zstyle ':completion:*:killall:*'   force-list always


#------------------------------
# Prompt
#------------------------------
function precmd {

    local TERMWIDTH
    (( TERMWIDTH = ${COLUMNS} - 1 ))


    ###
    # Truncate the path if it's too long.

    PR_FILLBAR=""
    PR_PWDLEN=""

    local promptsize=${#${(%):---(%n@%m:%1~)---()--}}
    local pwdsize=${#${(%):-%~}}

    if [[ "$promptsize + $pwdsize" -gt $TERMWIDTH ]]; then
        ((PR_PWDLEN=$TERMWIDTH - $promptsize))
    else
    PR_FILLBAR="\${(l.(($TERMWIDTH - ($promptsize + $pwdsize)))..${PR_HBAR}.)}"
    fi


    ###
    # Get APM info.

    if which ibam > /dev/null; then
    PR_APM_RESULT=`ibam --percentbattery`
    elif which apm > /dev/null; then
    PR_APM_RESULT=`apm`
    fi
}


setopt extended_glob
setopt extendedglob
preexec () {
    if [[ "$TERM" == "screen" ]]; then
    local CMD=${1[(wr)^(*=*|sudo|-*)]}
    echo -n "\ek$CMD\e\\"
    fi
}


setprompt () {
    ###
    # Need this so the prompt will work.

    setopt prompt_subst


    ###
    # See if we can use colors.

    autoload colors zsh/terminfo
    if [[ "$terminfo[colors]" -ge 8 ]]; then
    colors
    fi
    for color in RED GREEN YELLOW BLUE MAGENTA CYAN WHITE; do
    eval PR_$color='%{$terminfo[bold]$fg[${(L)color}]%}'
    eval PR_LIGHT_$color='%{$fg[${(L)color}]%}'
    (( count = $count + 1 ))
    done
    PR_NO_COLOUR="%{$terminfo[sgr0]%}"


    ###
    # See if we can use extended characters to look nicer.

    typeset -A altchar
    set -A altchar ${(s..)terminfo[acsc]}
    PR_SET_CHARSET="%{$terminfo[enacs]%}"
    PR_SHIFT_IN="%{$terminfo[smacs]%}"
    PR_SHIFT_OUT="%{$terminfo[rmacs]%}"
    PR_HBAR=${altchar[q]:--}
    PR_ULCORNER=${altchar[l]:--}
    PR_LLCORNER=${altchar[m]:--}
    PR_LRCORNER=${altchar[j]:--}
    PR_URCORNER=${altchar[k]:--}


    ###
    # Decide if we need to set titlebar text.

    case $TERM in
    xterm*)
        PR_TITLEBAR=$'%{\e]0;%(!.-=*[ROOT]*=- | .)%n@%m:%~ | ${COLUMNS}x${LINES} | %y\a%}'
        ;;
    screen)
        PR_TITLEBAR=$'%{\e_screen \005 (\005t) | %(!.-=[ROOT]=- | .)%n@%m:%~ | ${COLUMNS}x${LINES} | %y\e\\%}'
        ;;
    *)
        PR_TITLEBAR=''
        ;;
    esac


    ###
    # Decide whether to set a screen title
    if [[ "$TERM" == "screen" ]]; then
    PR_STITLE=$'%{\ekzsh\e\\%}'
    else
    PR_STITLE=''
    fi


    ###
    # APM detection

    if which ibam > /dev/null; then
    PR_APM='$PR_RED${${PR_APM_RESULT[(f)1]}[(w)-2]}%%(${${PR_APM_RESULT[(f)3]}[(w)-1]})$PR_LIGHT_BLUE:'
    elif which apm > /dev/null; then
    PR_APM='$PR_RED${PR_APM_RESULT[(w)5,(w)6]/\% /%%}$PR_LIGHT_BLUE:'
    else
    PR_APM=''
    fi


    ###
    # Finally, the prompt.

    PROMPT='$PR_SET_CHARSET$PR_STITLE${(e)PR_TITLEBAR}\
$PR_CYAN$PR_SHIFT_IN$PR_ULCORNER$PR_BLUE$PR_HBAR$PR_SHIFT_OUT(\
$PR_WHITE%(!.%SROOT%s.%n)$PR_WHITE@%m $PR_MAGENTA%1~\
$PR_BLUE)$PR_SHIFT_IN$PR_HBAR$PR_CYAN$PR_HBAR${(e)PR_FILLBAR}$PR_BLUE$PR_HBAR$PR_SHIFT_OUT(\
$PR_MAGENTA%$PR_PWDLEN<...<%~%<<\
$PR_BLUE)$PR_SHIFT_IN$PR_HBAR$PR_CYAN$PR_URCORNER$PR_SHIFT_OUT\

$PR_CYAN$PR_SHIFT_IN$PR_LLCORNER$PR_BLUE$PR_HBAR$PR_SHIFT_OUT(\
%(?..$PR_LIGHT_RED%?$PR_BLUE:)\
${(e)PR_APM}$PR_YELLOW%D{%H:%M}\
$PR_LIGHT_BLUE:%(!.$PR_RED.$PR_WHITE)%#$PR_BLUE)$PR_SHIFT_IN$PR_HBAR$PR_SHIFT_OUT\
$PR_CYAN$PR_SHIFT_IN$PR_HBAR$PR_SHIFT_OUT\
$PR_NO_COLOUR '

    RPROMPT=' $PR_CYAN$PR_SHIFT_IN$PR_HBAR$PR_BLUE$PR_HBAR$PR_SHIFT_OUT\
($PR_YELLOW%D{%a,%b%d}$PR_BLUE)$PR_SHIFT_IN$PR_HBAR$PR_CYAN$PR_LRCORNER$PR_SHIFT_OUT$PR_NO_COLOUR'

    PS2='$PR_CYAN$PR_SHIFT_IN$PR_HBAR$PR_SHIFT_OUT\
$PR_BLUE$PR_SHIFT_IN$PR_HBAR$PR_SHIFT_OUT(\
$PR_LIGHT_GREEN%_$PR_BLUE)$PR_SHIFT_IN$PR_HBAR$PR_SHIFT_OUT\
$PR_CYAN$PR_SHIFT_IN$PR_HBAR$PR_SHIFT_OUT$PR_NO_COLOUR '
}

setprompt
2
  • I think your prompt is really interesting (care to share its code in a comment field below?). Although it wasn't entirely what I was shooting for, which is to press a keyboard shortcut to jump between submitted commands (i.e. positions of former prompts in the current window).
    – Henrik
    Commented Nov 1, 2010 at 20:21
  • Most likely from Phil!'s ZSH Prompt, but many others have copied and modified for their own use. Phil!'s page gives a detailed description/breakdown of the code/script. I found may variations by doing a Google search for PR_HBAR, one of the variables.
    – Friartek
    Commented Sep 20, 2017 at 22:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .