Improved support for leading newline

* New modes that either print it only when it isn't the first line, or
    only add it (as well as a warning) if the last command didn't return
    a newline.
  * Overengineered af.
This commit is contained in:
Emmanuel BENOîT 2022-10-22 18:31:35 +02:00
parent eeed7e79a1
commit a595d71cbd
9 changed files with 149 additions and 11 deletions

View file

@ -142,8 +142,16 @@ The `layout_*` variables control the prompt's layout and general appearance:
default this entry contains an empty string.
* `layout_input_always` determines whether the input line should be rendered
even if no generators are specified (`0` or `1`, default `0`).
* `layout_empty_line` prints an empty line before the prompt's top line. This
prevents display problems when some command outputs a line without `\n`.
* `layout_empty_line` determines how the prompt handles printing an empty line
before the prompt's top line.
* When set to `0`, no extra line is drawn, and commands that do not end with
an EOL will cause the prompt's first line to be displayed incorrectly.
* When set to `1`, the prompt's top line will always be preceeded with an
empty line.
* When set to `2`, the prompt will be preceeded by an empty line unless it
is being drawn on the terminal's first line.
* When set to `3`, a newline will be added to the prompt if the last
command's output didn't end with a newline.
The `term_*` variables control the prompt's ability to change the terminal's
title and/or icon title:

View file

@ -33,8 +33,9 @@
] ,
# - Always generate input line?
layout_input_always => 0 ,
# - Add an empty line before the prompt?
layout_empty_line => 0 ,
# - Add an empty line before the prompt? 0=no, 1=always, 2=not at the top
# of the terminal, 3=only if the previous command didn't finish with \n
layout_empty_line => 3 ,
# TERMINAL TITLE
# - Set title from the prompt? 0=no, 1=normal, 2=minimized, 3=both

View file

@ -12,7 +12,7 @@ use strict;
use warnings;
use utf8;
use open ':std', ':encoding(UTF-8)';
use POSIX qw(strftime);
use POSIX qw(strftime :termios_h);
use Cwd qw(abs_path getcwd);
@ -45,8 +45,9 @@ our %CONFIG = (
layout_input => [ qw( userhost cwd ) ] ,
# - Always generate input line?
layout_input_always => 0 ,
# - Add an empty line before the prompt?
layout_empty_line => 0 ,
# - Add an empty line before the prompt? 0=no, 1=always, 2=not at the top
# of the terminal, 3=only if the previous command didn't finish with \n
layout_empty_line => 3 ,
# TERMINAL TITLE
# - Set title from the prompt? 0=no, 1=normal, 2=minimized, 3=both
@ -151,6 +152,13 @@ sub default_theme
'bg_ps2' => -2,
ps2_suffix => ' : ' ,
# Text appended to a line without EOL when layout_empty_line is 3
'noeol_text' => '<NO EOL>' ,
# Colors and style for the above text
'noeol_fg' => 1 ,
'noeol_bg' => -1 ,
'noeol_style' => 'b' ,
# Current working directory - Truncation string
cwd_trunc => '...' ,
# Current working directory - Foreground / background colors
@ -302,6 +310,51 @@ sub set_color
return tput_sequence( "seta$type $index" );
}
sub get_cursor_pos
{
local $| = 1;
open(my $ttyIn, '<:bytes' , '/dev/tty');
open(my $ttyOut, '>:bytes' , '/dev/tty');
# Enable raw mode
my $term = POSIX::Termios->new;
my $ttyInFd = fileno $ttyIn;
$term->getattr($ttyInFd);
my $oTerm = $term ->getlflag;
$term->setlflag($oTerm & ~( ECHO | ECHOK | ICANON ));
$term->setcc(VTIME, 1);
$term->setattr($ttyInFd, TCSANOW);
# Read position
syswrite $ttyOut, "\033[6n", 4;
my ($input, $col, $line) = ("", "", "");
my $state = 0;
while (sysread $ttyIn, $input, 1) {
if ($state == 0) {
$state = 1 if $input eq '[';
} elsif ($state == 1) {
if ($input eq ';') {
$state = 2;
} else {
$line .= $input;
}
} elsif ($state == 2) {
last if $input eq 'R';
$col .= $input;
}
}
# Enable cooked mode
$term->setlflag($oTerm);
$term->setcc(VTIME, 0);
$term->setattr($ttyInFd, TCSANOW);
close $ttyIn;
close $ttyOut;
return $line, $col;
}
#}}}
# Theming support -----------------------------------------------------------{{{
@ -593,6 +646,33 @@ sub render
#}}}
# Prompt parts --------------------------------------------------------------{{{
sub gen_empty_line
{
my $lel = $CONFIG{layout_empty_line};
my $nl;
my $out = "";
if ($lel > 1) {
my ($line, $col) = get_cursor_pos;
$nl = ( $lel == 2 && $line != 1 ) || ( $lel == 3 && $col != 1 );
if ( $lel == 3 && $col != 1 ) {
$out .= render('input', {
content => [
{
style => themed 'noeol_style' ,
fg => themed 'noeol_fg' ,
bg => themed 'noeol_bg' ,
},
( themed 'noeol_text' )
]
});
}
} else {
$nl = $lel
}
$out .= "\\n" if $nl;
return $out;
}
sub gen_top_line
{
my @left = @{ $CONFIG{layout_left} };
@ -750,17 +830,24 @@ _gprompt_set_return() {
return "\${1:-0}"
}
gprompt_command() {
local cmd_status=\$?
_GPROMPT_PREV_STATUS=\$?
local jobs=(\$(jobs -p))
eval "\$_GPROMPT_PREVIOUS_PCMD"
eval "\$( perl \Q$gpPath\E "rc:\$cmd_status" "jobs:\${#jobs[@]}" )"
_gprompt_set_return "\$cmd_status"
eval "\$( perl \Q$gpPath\E "rc:\$_GPROMPT_PREV_STATUS" "jobs:\${#jobs[@]}" )"
_gprompt_set_return "\$_GPROMPT_PREV_STATUS"
}
_gprompt_clear() {
clear -x
_gprompt_set_return "\${_GPROMPT_PREV_STATUS:-0}"
gprompt_command
echo -n "\${PS1\@P}\r"
}
shopt -s checkwinsize
if [[ \$PROMPT_COMMAND != *"gprompt_command"* ]]; then
_GPROMPT_PREVIOUS_PCMD="\$PROMPT_COMMAND"
PROMPT_COMMAND="gprompt_command"
fi
bind -x \$'"\\C-l":_gprompt_clear'
EOF
exit 0;
}
@ -793,7 +880,7 @@ sub main
%TLEN = compute_trans_lengths;
my $pg = gen_term_title;
my $ps1 = $pg;
$ps1 .= "\\n" if $CONFIG{layout_empty_line};
$ps1 .= gen_empty_line;
$ps1 .= gen_top_line;
my ( $ill , $ilt ) = gen_input_line;
$ps1 .= $ilt;

View file

@ -42,6 +42,13 @@
'bg_ps2' => thref 'bg',
ps2_suffix => '\b2\f3| ' ,
# Text appended to a line without EOL when layout_empty_line is 3
'noeol_text' => '<NO EOL>' ,
# Colors and style for the above text
'noeol_fg' => thref 'fg3' ,
'noeol_bg' => thref 'bg3' ,
'noeol_style' => 'b' ,
# Current working directory - Truncation string
cwd_trunc => '...' ,
# Current working directory - Foreground / background colors

View file

@ -42,6 +42,13 @@
'bg_ps2' => thref 'bg',
ps2_suffix => '\b2\f3| ' ,
# Text appended to a line without EOL when layout_empty_line is 3
'noeol_text' => '<NO EOL>' ,
# Colors and style for the above text
'noeol_fg' => thref 'fg3' ,
'noeol_bg' => thref 'bg3' ,
'noeol_style' => 'b' ,
# Current working directory - Truncation string
cwd_trunc => '...' ,
# Current working directory - Foreground / background colors

View file

@ -42,6 +42,13 @@
'bg_ps2' => thref 'bg',
'ps2_suffix' => "\\b2\\f3\x{250a} ",
# Text appended to a line without EOL when layout_empty_line is 3
'noeol_text' => "\x{b6}" ,
# Colors and style for the above text
'noeol_fg' => thref 'fg3' ,
'noeol_bg' => thref 'bg3' ,
'noeol_style' => 'b' ,
# Current working directory - Truncation string
'cwd_trunc' => "\x{2026}",
# Current working directory - Foreground / background colors

View file

@ -42,6 +42,13 @@
'bg_ps2' => thref 'bg',
'ps2_suffix' => "\\b2\\f3\x{250a} ",
# Text appended to a line without EOL when layout_empty_line is 3
'noeol_text' => "\x{b6}" ,
# Colors and style for the above text
'noeol_fg' => thref 'fg3' ,
'noeol_bg' => thref 'bg3' ,
'noeol_style' => 'b' ,
# Current working directory - Truncation string
'cwd_trunc' => "\x{2026}",
# Current working directory - Foreground / background colors

View file

@ -41,6 +41,13 @@
'bg_ps2' => 234,
'ps2_suffix' => '\f0\b2'."\x{e0b0}".'\f2\b1'."\x{e0b0}".' ' ,
# Text appended to a line without EOL when layout_empty_line is 3
'noeol_text' => "\x{e0b0} \x{26a0} \x{e0b2}" ,
# Colors and style for the above text
'noeol_fg' => thref 'fg3' ,
'noeol_bg' => thref 'bg3' ,
'noeol_style' => 'b' ,
# Current working directory - Truncation string
'cwd_trunc' => "\x{2026}",
# Current working directory - Foreground / background colors

View file

@ -41,6 +41,13 @@
'bg_ps2' => 234,
'ps2_suffix' => '\f0\b2'."\x{e0b0}".'\f2\b1'."\x{e0b0}".' ' ,
# Text appended to a line without EOL when layout_empty_line is 3
'noeol_text' => "\x{e0b0} \x{26a0} \x{e0b2}" ,
# Colors and style for the above text
'noeol_fg' => thref 'fg3' ,
'noeol_bg' => thref 'bg3' ,
'noeol_style' => 'b' ,
# Current working directory - Truncation string
'cwd_trunc' => "\x{2026}",
# Current working directory - Foreground / background colors