#!/usr/bin/env perl use warnings; use strict; use 5.10.0; use Text::LineFold; use Term::ReadKey qw(GetTerminalSize ReadKey ReadMode); END { ReadMode 0 } use constant { BSPACE => 0x7f, CLEAR_LINE => "\e[2K", GO_TO_TOP_LEFT => "\e[1;1H", CLEAR_EOS => "\e[0J", }; sub local_readline { my ( $text ) = @_; my $p = "\r: "; my $str = ''; my $line_fold = Text::LineFold->new( ColMax => ( GetTerminalSize )[0] ); print GO_TO_TOP_LEFT; print CLEAR_EOS; print $line_fold->fold( $text, 'PLAIN' ); print $p . $str; my $size_changed = 0; my $orig_sigwinch = $SIG{'WINCH'}; local $SIG{'WINCH'} = sub { $orig_sigwinch->() if $orig_sigwinch && ref $orig_sigwinch eq 'CODE'; $size_changed = 1; }; ReadMode 4; while ( 1 ) { ##### if ( $size_changed ) { $size_changed = 0; $line_fold->config( 'ColMax', ( GetTerminalSize )[0] ); print GO_TO_TOP_LEFT; print CLEAR_EOS; print $line_fold->fold( $text, 'PLAIN' ); print $p . $str; } my $key = ReadKey( -1 ); next if ! defined $key; ##### if ( $key eq "\cC" ) { say "^C"; exit 1 } if ( $key eq "\cD" ) { return } if ( $key eq "\n" ) { print "\n"; return $str } if ( ord( $key ) == BSPACE || $key eq "\cH" ) { $str =~ s/.\z//; print CLEAR_LINE; print $p . $str; next; } next if $key !~ /^\p{Print}\z/; $str .= $key; print $p . $str; } ReadMode 0 } say local_readline( 'Long Prompt Line ' x 20 . "\n\n" );