diff options
Diffstat (limited to 'contrib/replxx/src/prompt.cxx')
-rw-r--r-- | contrib/replxx/src/prompt.cxx | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/contrib/replxx/src/prompt.cxx b/contrib/replxx/src/prompt.cxx new file mode 100644 index 0000000..c13ea80 --- /dev/null +++ b/contrib/replxx/src/prompt.cxx @@ -0,0 +1,144 @@ +#ifdef _WIN32 + +#include <conio.h> +#include <windows.h> +#include <io.h> +#if _MSC_VER < 1900 && defined (_MSC_VER) +#define snprintf _snprintf // Microsoft headers use underscores in some names +#endif +#define strcasecmp _stricmp +#define strdup _strdup +#define write _write +#define STDIN_FILENO 0 + +#else /* _WIN32 */ + +#include <unistd.h> + +#endif /* _WIN32 */ + +#include "prompt.hxx" +#include "util.hxx" + +namespace replxx { + +Prompt::Prompt( Terminal& terminal_ ) + : _extraLines( 0 ) + , _lastLinePosition( 0 ) + , _cursorRowOffset( 0 ) + , _screenColumns( 0 ) + , _terminal( terminal_ ) { +} + +void Prompt::write() { + _terminal.write32( _text.get(), _text.length() ); +} + +void Prompt::update_screen_columns( void ) { + _screenColumns = _terminal.get_screen_columns(); +} + +void Prompt::set_text( UnicodeString const& text_ ) { + _text = text_; + update_state(); +} + +void Prompt::update_state() { + _cursorRowOffset -= _extraLines; + _extraLines = 0; + _lastLinePosition = 0; + _screenColumns = 0; + update_screen_columns(); + // strip control characters from the prompt -- we do allow newline + UnicodeString::const_iterator in( _text.begin() ); + UnicodeString::iterator out( _text.begin() ); + + int visibleCount = 0; + int x = 0; + + bool const strip = !tty::out; + + while (in != _text.end()) { + char32_t c = *in; + if ('\n' == c || !is_control_code(c)) { + *out = c; + ++out; + ++in; + ++visibleCount; + if ('\n' == c || ++x >= _screenColumns) { + x = 0; + ++_extraLines; + _lastLinePosition = visibleCount; + } + } else if (c == '\x1b') { + if ( strip ) { + // jump over control chars + ++in; + if (*in == '[') { + ++in; + while ( ( in != _text.end() ) && ( ( *in == ';' ) || ( ( ( *in >= '0' ) && ( *in <= '9' ) ) ) ) ) { + ++in; + } + if (*in == 'm') { + ++in; + } + } + } else { + // copy control chars + *out = *in; + ++out; + ++in; + if (*in == '[') { + *out = *in; + ++out; + ++in; + while ( ( in != _text.end() ) && ( ( *in == ';' ) || ( ( ( *in >= '0' ) && ( *in <= '9' ) ) ) ) ) { + *out = *in; + ++out; + ++in; + } + if (*in == 'm') { + *out = *in; + ++out; + ++in; + } + } + } + } else { + ++in; + } + } + _characterCount = visibleCount; + int charCount( static_cast<int>( out - _text.begin() ) ); + _text.erase( charCount, _text.length() - charCount ); + + _cursorRowOffset += _extraLines; +} + +int Prompt::indentation() const { + return _characterCount - _lastLinePosition; +} + +// Used with DynamicPrompt (history search) +// +const UnicodeString forwardSearchBasePrompt("(i-search)`"); +const UnicodeString reverseSearchBasePrompt("(reverse-i-search)`"); +const UnicodeString endSearchBasePrompt("': "); + +DynamicPrompt::DynamicPrompt( Terminal& terminal_, int initialDirection ) + : Prompt( terminal_ ) + , _searchText() + , _direction( initialDirection ) { + updateSearchPrompt(); +} + +void DynamicPrompt::updateSearchPrompt(void) { + update_screen_columns(); + const UnicodeString* basePrompt = + (_direction > 0) ? &forwardSearchBasePrompt : &reverseSearchBasePrompt; + _text.assign( *basePrompt ).append( _searchText ).append( endSearchBasePrompt ); + update_state(); +} + +} + |