Seu caso de uso não é muito convincente. A maioria das pessoas inclui o diretório atual como parte de seu prompt; O zsh possui possibilidades de configuração de prompt extremamente ricas (incluindo avisos de múltiplas linhas, avisos para a esquerda e para a direita, etc.). Com a conclusão (que novamente no zsh é muito configurável), você pode mostrar listas de arquivos nos contextos onde você precisa deles. Dito isto, existem maneiras de conseguir o que você descreve, mas nenhuma é fácil e agradável.
Com o shell apenas
O shell está apenas no controle de sua própria entrada e saída. Quando você executa um comando, o shell não está no controle de nada. Se você quiser reservar uma parte do terminal para coisas como ls
output, você precisa da cooperação do terminal. Qual é a diferença exata entre um 'terminal', um 'shell', um 'tty' e um 'console'? pode ser um plano de fundo útil.
Em alguns terminais, você pode definir uma região rolável; o que está fora da região rolável permanece no lugar. Eu sei que o xterm suporta esse recurso, não sei se outros emuladores de terminal populares fazem isso. Aqui está uma prova de conceito para exibir a saída de date
, pwd
e ls
no terço inferior do terminal.
reset () {
tput reset
scrollable_lines=$((LINES*2/3))
tput csr 0 $((scrollable_lines-1))
}
update_status () {
tput sc
tput cup $((scrollable_lines+2)) 0
tput ed
date
pwd
ls -x --color=always | head -n $((LINES-scrollable_lines-3))
tput rc
}
PROMPT_COMMAND='update_status'
reset
Algumas palavras de explicação:
- O comando
tput
envia seqüências de controle obtidas via terminfo para o terminal. - A chamada para
tput csr
define a região de rolagem para as 2/3 linhas principais. - A função
reset
precisa ser executada em uma reinicialização do terminal, porque uma reinicialização do terminal redefine a região de rolagem para ser o terminal inteiro. -
tput sc
salva a posição do cursor, a ser restaurada posteriormente comtput rc
. -
tput cup
move o cursor para o topo da região sem rolagem.tput ed
apaga o que já está lá. - A função
update_status
é executada toda vez que bash está prestes a exibir um novo prompt.
Eu tentei isso em zsh, mas ele interage com o terminal mais do que o bash, então mesmo uma prova de conceito requer mais ajuste.
Com um multiplexador de terminal
Ambas as Tela e O Tmux pode dividir o terminal em várias sub-janelas (a tela chama essas regiões, o tmux as chama de painéis). Você pode executar um multiplexador, executar seu shell na janela superior e executá-lo em outras coisas na janela inferior.
É fácil acionar algo no shell para fazer com que as coisas sejam exibidas na janela inferior: basta redirecionar a saída para o dispositivo terminal correto. A parte complicada aqui é obter o nome do dispositivo e manter a janela inferior aberta o quanto for necessário, mas não mais.
Aqui está uma prova de conceito usando zsh e screen. Executar screen -c ~/etc/split.screenrc
onde ~/etc/split.screenrc
contém
escape ^\\
hardstatus off
split
focus
resize 10
screen ~/bin/bottom_tty
focus
screen zsh
Isso cria uma região inferior de 10 linhas que executa o programa ~/bin/bottom_tty
e executa zsh na região superior. Em ~/bin/bottom_tty
, obtenha alguns parâmetros e durma para sempre:
#!/bin/sh
cat <<EOF >~/.split-screen.$PPID.tmp
bottom_tty=$(tty)
bottom_lines=$(tput lines)
bottom_pid=$$
EOF
mv ~/.split-screen.$PPID.tmp ~/.split-screen.$PPID
while true; do sleep 999999999; done
Em .zshrc
, leia as informações e configure algumas coisas:
- Sempre que um prompt for exibido, execute
refresh_bottom_tty
para atualizar o conteúdo da região inferior. - Quando o zsh sair, mate o programa na região inferior, para que o script termine.
refresh_bottom_tty () {
printf %s $terminfo[clear]
date
pwd
ls -x --color | head -n $((bottom_lines-2))
}
precmd () {
refresh_bottom_tty <>$bottom_tty 1>&0 2>&0
}
zshexit () {
kill -HUP -$bottom_pid
}
while [[ ! -e ~/.split-screen.$PPID ]]; do
sleep 1
done
. ~/.split-screen.$PPID
rm ~/.split-screen.$PPID
Wrapper de terminal dedicado
Seria possível fazer um trabalho muito melhor e mais robusto com um wrapper dedicado que entende o que você quer fazer com ele. O wrapper definiria um terminal virtual no qual o shell é executado e haveria uma interface para permitir que o shell atualize o que é exibido fora do terminal virtual.
A tela e o tmux estão realmente próximos de fornecer a funcionalidade necessária, por meio da linha de status. No entanto, ambos estão limitados a uma única linha de status. Se eles forem estendidos para suportar linhas de status de várias linhas, você poderá exibir o que deseja lá.
Como alternativa, você pode usar o módulo zpty para escrever um invólucro dedicado. Haveria então duas instâncias de zsh: uma para o wrapper, uma para executar os comandos. Conseguir isso até mesmo para uma prova de conceito é mais código do que eu gostaria de escrever nesta resposta.