summaryrefslogtreecommitdiffstats
path: root/contrib/replxx/src/prompt.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/replxx/src/prompt.cxx')
-rw-r--r--contrib/replxx/src/prompt.cxx144
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();
+}
+
+}
+