Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for custom descriptors #26

Merged
merged 3 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/replxx.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ typedef struct ReplxxHistoryEntryTag {
*
* \return Replxx library resource holder.
*/
REPLXX_IMPEXP Replxx* replxx_init( void );
// REPLXX_IMPEXP Replxx* replxx_init( void );

/*! \brief Cleanup resources used by Replxx library.
*
Expand Down
2 changes: 1 addition & 1 deletion include/replxx.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ private:
#endif

public:
Replxx( void );
Replxx( std::istream & input_stream_, std::ostream & output_stream_, int in_fd_, int out_fd_, int err_fd_ );
Replxx( Replxx&& ) = default;
Replxx& operator = ( Replxx&& ) = default;

Expand Down
412 changes: 206 additions & 206 deletions src/escape.cxx

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/escape.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace EscapeSequenceProcessing {
// dispatch routines, then eventually returns the final (possibly extended or
// special) character.
//
typedef char32_t (*CharacterDispatchRoutine)(char32_t);
typedef char32_t (*CharacterDispatchRoutine)(int, int, char32_t);

// This structure is used by doDispatch() to hold a list of characters to test
// for and
Expand All @@ -27,7 +27,7 @@ struct CharacterDispatch {
CharacterDispatchRoutine* dispatch; // array of routines to call
};

char32_t doDispatch(char32_t c);
char32_t doDispatch(int in_fd_, int err_fd, char32_t c);

}

Expand Down
18 changes: 9 additions & 9 deletions src/replxx.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ void delete_ReplxxImpl( Replxx::ReplxxImpl* impl_ ) {
}
}

Replxx::Replxx( void )
: _impl( new Replxx::ReplxxImpl( nullptr, nullptr, nullptr ), delete_ReplxxImpl ) {
Replxx::Replxx( std::istream & input_stream_, std::ostream & output_stream_, int in_fd_, int out_fd_, int err_fd_ )
: _impl( new Replxx::ReplxxImpl( input_stream_, output_stream_, in_fd_, out_fd_, err_fd_ ), delete_ReplxxImpl ) {
}

void Replxx::set_completion_callback( completion_callback_t const& fn ) {
Expand Down Expand Up @@ -339,10 +339,10 @@ Replxx::Color rgb666( int red_, int green_, int blue_ ) {

}

::Replxx* replxx_init() {
typedef ::Replxx* replxx_data_t;
return ( reinterpret_cast<replxx_data_t>( new replxx::Replxx::ReplxxImpl( nullptr, nullptr, nullptr ) ) );
}
// ::Replxx* replxx_init() {
// typedef ::Replxx* replxx_data_t;
// return ( reinterpret_cast<replxx_data_t>( new replxx::Replxx::ReplxxImpl( nullptr, nullptr, nullptr ) ) );
// }

void replxx_end( ::Replxx* replxx_ ) {
delete reinterpret_cast<replxx::Replxx::ReplxxImpl*>( replxx_ );
Expand Down Expand Up @@ -683,7 +683,7 @@ int replxx_history_size( ::Replxx* replxx_ ) {
void replxx_debug_dump_print_codes(void) {
char quit[4];

printf(
dprintf(_out_fd,
"replxx key codes debugging mode.\n"
"Press keys to see scan codes. Type 'quit' at any time to exit.\n");
if (enableRawMode() == -1) return;
Expand All @@ -702,9 +702,9 @@ void replxx_debug_dump_print_codes(void) {
quit[sizeof(quit) - 1] = c; /* Insert current char on the right. */
if (memcmp(quit, "quit", sizeof(quit)) == 0) break;

printf("'%c' %02x (%d) (type quit to exit)\n", isprint(c) ? c : '?', (int)c,
dprintf(_out_fd,"'%c' %02x (%d) (type quit to exit)\n", isprint(c) ? c : '?', (int)c,
(int)c);
printf("\r"); /* Go left edge manually, we are in raw mode. */
dprintf(_out_fd,"\r"); /* Go left edge manually, we are in raw mode. */
fflush(stdout);
}
disableRawMode();
Expand Down
71 changes: 38 additions & 33 deletions src/replxx_impl.cxx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <algorithm>
#include <cstdio>
#include <memory>
#include <cerrno>
#include <iostream>
Expand Down Expand Up @@ -146,7 +147,7 @@ class IOModeGuard {

}

Replxx::ReplxxImpl::ReplxxImpl( FILE*, FILE*, FILE* )
Replxx::ReplxxImpl::ReplxxImpl( std::istream & in_, std::ostream & out_, int in_fd_, int out_fd_, int err_fd_ )
: _utf8Buffer()
, _data()
, _pos( 0 )
Expand Down Expand Up @@ -175,7 +176,7 @@ Replxx::ReplxxImpl::ReplxxImpl( FILE*, FILE*, FILE* )
, _indentMultiline( true )
, _namedActions()
, _keyPressHandlers()
, _terminal()
, _terminal(in_fd_, out_fd_)
, _currentThread()
, _prompt( _terminal )
, _completionCallback( nullptr )
Expand All @@ -200,7 +201,12 @@ Replxx::ReplxxImpl::ReplxxImpl( FILE*, FILE*, FILE* )
, _oldPos( 0 )
, _moveCursor( false )
, _ignoreCase( false )
, _mutex() {
, _mutex()
, _in(in_)
, _out(out_)
, _in_fd(in_fd_)
, _out_fd(out_fd_)
, _err_fd(err_fd_) {
using namespace std::placeholders;
_namedActions[action_names::INSERT_CHARACTER] = std::bind( &ReplxxImpl::invoke, this, Replxx::ACTION::INSERT_CHARACTER, _1 );
_namedActions[action_names::NEW_LINE] = std::bind( &ReplxxImpl::invoke, this, Replxx::ACTION::NEW_LINE, _1 );
Expand Down Expand Up @@ -605,8 +611,8 @@ void Replxx::ReplxxImpl::set_preload_buffer( std::string const& preloadText ) {

char const* Replxx::ReplxxImpl::read_from_stdin( void ) {
if ( _preloadedBuffer.empty() ) {
getline( cin, _preloadedBuffer );
if ( ! cin.good() ) {
getline( _in, _preloadedBuffer );
if ( ! _in.good() ) {
return nullptr;
}
}
Expand All @@ -629,17 +635,17 @@ void Replxx::ReplxxImpl::emulate_key_press( char32_t keyCode_ ) {
char const* Replxx::ReplxxImpl::input( std::string const& prompt ) {
try {
errno = 0;
if ( ! tty::in ) { // input not from a terminal, we should work with piped input, i.e. redirected stdin
if ( ! tty::is_a_tty(_in_fd) ) { // input not from a terminal, we should work with piped input, i.e. redirected stdin
return ( read_from_stdin() );
}
if ( ! _errorMessage.empty() ) {
printf( "%s", _errorMessage.c_str() );
fflush( stdout );
dprintf( _out_fd, "%s", _errorMessage.c_str() );
fdatasync( _out_fd );
_errorMessage.clear();
}
if ( isUnsupportedTerm() ) {
fprintf( stdout, "%s", prompt.c_str() );
fflush( stdout );
dprintf( _out_fd, "%s", prompt.c_str() );
fdatasync( _out_fd );
return ( read_from_stdin() );
}
std::unique_lock<std::mutex> l( _mutex );
Expand Down Expand Up @@ -975,7 +981,7 @@ Replxx::ReplxxImpl::paren_info_t Replxx::ReplxxImpl::matching_paren( void ) {

int Replxx::ReplxxImpl::virtual_render( char32_t const* buffer_, int len_, int& xPos_, int& yPos_, Prompt const* prompt_ ) {
Prompt const& prompt( prompt_ ? *prompt_ : _prompt );
return ( replxx::virtual_render( buffer_, len_, xPos_, yPos_, prompt.screen_columns(), _indentMultiline ? prompt.indentation() : 0 ) );
return ( replxx::virtual_render( buffer_, len_, xPos_, yPos_, prompt.screen_columns(), _indentMultiline ? prompt.indentation() : 0 ), _out_fd);
}

/**
Expand Down Expand Up @@ -1143,7 +1149,7 @@ char32_t Replxx::ReplxxImpl::do_complete_line( bool showCompletions_ ) {

// if no completions, we are done
if ( _completions.empty() ) {
beep();
beep(_err_fd);
return 0;
}

Expand All @@ -1162,7 +1168,7 @@ char32_t Replxx::ReplxxImpl::do_complete_line( bool showCompletions_ ) {
longestCommonPrefix = longest_common_prefix( _completions, _ignoreCase && lowerCaseContext );
}
if ( _beepOnAmbiguousCompletion && ( completionsCount != 1 ) ) { // beep if ambiguous
beep();
beep(_err_fd);
}

// if we can extend the item, extend it and return to main loop
Expand Down Expand Up @@ -1226,8 +1232,8 @@ char32_t Replxx::ReplxxImpl::do_complete_line( bool showCompletions_ ) {
_pos = _data.length();
refresh_line();
_pos = savePos;
printf( "\nDisplay all %u possibilities? (y or n)", static_cast<unsigned int>( _completions.size() ) );
fflush(stdout);
dprintf(_out_fd, "\nDisplay all %u possibilities? (y or n)", static_cast<unsigned int>( _completions.size() ) );
fdatasync(_out_fd);
onNewLine = true;
while (c != 'y' && c != 'Y' && c != 'n' && c != 'N' && c != Replxx::KEY::control('C')) {
do {
Expand Down Expand Up @@ -1275,15 +1281,15 @@ char32_t Replxx::ReplxxImpl::do_complete_line( bool showCompletions_ ) {
size_t rowCount = (_completions.size() + columnCount - 1) / columnCount;
for (size_t row = 0; row < rowCount; ++row) {
if (row == pauseRow) {
printf("\n--More--");
fflush(stdout);
dprintf(_out_fd, "\n--More--");
fdatasync(_out_fd);
c = 0;
bool doBeep = false;
while (c != ' ' && c != Replxx::KEY::ENTER && c != 'y' && c != 'Y' &&
c != 'n' && c != 'N' && c != 'q' && c != 'Q' &&
c != Replxx::KEY::control('C')) {
if (doBeep) {
beep();
beep(_err_fd);
}
doBeep = true;
do {
Expand All @@ -1294,18 +1300,18 @@ char32_t Replxx::ReplxxImpl::do_complete_line( bool showCompletions_ ) {
case ' ':
case 'y':
case 'Y':
printf("\r \r");
dprintf(_out_fd, "\r \r");
pauseRow += _terminal.get_screen_rows() - 1;
break;
case Replxx::KEY::ENTER:
printf("\r \r");
dprintf(_out_fd, "\r \r");
++pauseRow;
break;
case 'n':
case 'N':
case 'q':
case 'Q':
printf("\r \r");
dprintf(_out_fd, "\r \r");
stopList = true;
break;
case Replxx::KEY::control('C'):
Expand All @@ -1326,7 +1332,7 @@ char32_t Replxx::ReplxxImpl::do_complete_line( bool showCompletions_ ) {
if ( index < _completions.size() ) {
Completion const& c( _completions[index] );
int itemLength = static_cast<int>(c.text().length());
fflush(stdout);
fdatasync(_out_fd);

if ( longestCommonPrefix > 0 ) {
static UnicodeString const col( ansi_color( Replxx::Color::BRIGHTMAGENTA ) );
Expand All @@ -1350,13 +1356,13 @@ char32_t Replxx::ReplxxImpl::do_complete_line( bool showCompletions_ ) {

if ( ((column + 1) * rowCount) + row < _completions.size() ) {
for ( int k( itemLength ); k < longestCompletion; ++k ) {
printf( " " );
dprintf(_out_fd, " " );
}
}
}
}
}
fflush(stdout);
fdatasync(_out_fd);
}

// display the prompt on a new line, then redisplay the input buffer
Expand Down Expand Up @@ -1471,7 +1477,7 @@ Replxx::ACTION_RESULT Replxx::ReplxxImpl::insert_character( char32_t c ) {
* don't insert control characters
*/
if ( ( c >= static_cast<int>( Replxx::KEY::BASE ) ) || ( is_control_code( c ) && ( c != '\n' ) ) ) {
beep();
beep(_err_fd);
return ( Replxx::ACTION_RESULT::CONTINUE );
}
if ( ! _overwrite || ( _pos >= _data.length() ) ) {
Expand Down Expand Up @@ -1680,20 +1686,20 @@ Replxx::ACTION_RESULT Replxx::ReplxxImpl::yank( char32_t ) {
_killRing.lastAction = KillRing::actionYank;
_lastYankSize = restoredText->length();
} else {
beep();
beep(_err_fd);
}
return ( Replxx::ACTION_RESULT::CONTINUE );
}

// meta-Y, "yank-pop", rotate popped text
Replxx::ACTION_RESULT Replxx::ReplxxImpl::yank_cycle( char32_t ) {
if ( _killRing.lastAction != KillRing::actionYank ) {
beep();
beep(_err_fd);
return ( Replxx::ACTION_RESULT::CONTINUE );
}
UnicodeString* restoredText = _killRing.yankPop();
if ( !restoredText ) {
beep();
beep(_err_fd);
return ( Replxx::ACTION_RESULT::CONTINUE );
}
_pos -= _lastYankSize;
Expand Down Expand Up @@ -2303,7 +2309,7 @@ Replxx::ACTION_RESULT Replxx::ReplxxImpl::incremental_history_search( char32_t s
_history.restore_pos();
historyLinePosition = _pos;
} else {
beep();
beep(_err_fd);
}
} break;

Expand All @@ -2315,7 +2321,7 @@ Replxx::ACTION_RESULT Replxx::ReplxxImpl::incremental_history_search( char32_t s
dp._searchText.insert( dp._searchText.length(), c );
dp.updateSearchPrompt();
} else {
beep();
beep(_err_fd);
}
}
} // switch
Expand Down Expand Up @@ -2360,7 +2366,7 @@ Replxx::ACTION_RESULT Replxx::ReplxxImpl::incremental_history_search( char32_t s
lineSearchPos = ( dp._direction > 0 ) ? 0 : ( activeHistoryLine.length() - dp._searchText.length() );
} else {
historyLinePosition = _pos;
beep();
beep(_err_fd);
break;
}
} // while
Expand Down Expand Up @@ -2410,7 +2416,7 @@ Replxx::ACTION_RESULT Replxx::ReplxxImpl::bracketed_paste( char32_t ) {
static const UnicodeString BRACK_PASTE_SUFF( "\033[201~" );
static const int BRACK_PASTE_SLEN( BRACK_PASTE_SUFF.length() );
UnicodeString buf;
while ( char32_t c = read_unicode_character() ) {
while ( char32_t c = read_unicode_character(_in_fd) ) {
if ( ( c == '\r' ) || ( c == KEY::control( 'M' ) ) ) {
c = '\n';
}
Expand Down Expand Up @@ -2588,4 +2594,3 @@ void Replxx::ReplxxImpl::dynamic_refresh(Prompt& oldPrompt, Prompt& newPrompt, c
}

}

8 changes: 7 additions & 1 deletion src/replxx_impl.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,14 @@ private:
bool _moveCursor;
bool _ignoreCase;
mutable std::mutex _mutex;

std::istream & _in;
[[ maybe_unused ]] std::ostream & _out;
int _in_fd = 0;
int _out_fd = 1;
int _err_fd = 2;
public:
ReplxxImpl( FILE*, FILE*, FILE* );
ReplxxImpl( std::istream & in_, std::ostream & out_, int in_fd_, int out_fd_, int err_fd_ );
virtual ~ReplxxImpl( void );
void set_modify_callback( Replxx::modify_callback_t const& fn );
void set_completion_callback( Replxx::completion_callback_t const& fn );
Expand Down
Loading