您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

prompt.cxx 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #ifdef _WIN32
  2. #include <conio.h>
  3. #include <windows.h>
  4. #include <io.h>
  5. #if _MSC_VER < 1900 && defined (_MSC_VER)
  6. #define snprintf _snprintf // Microsoft headers use underscores in some names
  7. #endif
  8. #define strcasecmp _stricmp
  9. #define strdup _strdup
  10. #define write _write
  11. #define STDIN_FILENO 0
  12. #else /* _WIN32 */
  13. #include <unistd.h>
  14. #endif /* _WIN32 */
  15. #include "prompt.hxx"
  16. #include "util.hxx"
  17. namespace replxx {
  18. Prompt::Prompt( Terminal& terminal_ )
  19. : _extraLines( 0 )
  20. , _lastLinePosition( 0 )
  21. , _cursorRowOffset( 0 )
  22. , _screenColumns( 0 )
  23. , _terminal( terminal_ ) {
  24. }
  25. void Prompt::write() {
  26. _terminal.write32( _text.get(), _text.length() );
  27. }
  28. void Prompt::update_screen_columns( void ) {
  29. _screenColumns = _terminal.get_screen_columns();
  30. }
  31. void Prompt::set_text( UnicodeString const& text_ ) {
  32. _text = text_;
  33. update_state();
  34. }
  35. void Prompt::update_state() {
  36. _cursorRowOffset -= _extraLines;
  37. _extraLines = 0;
  38. _lastLinePosition = 0;
  39. _screenColumns = 0;
  40. update_screen_columns();
  41. // strip control characters from the prompt -- we do allow newline
  42. UnicodeString::const_iterator in( _text.begin() );
  43. UnicodeString::iterator out( _text.begin() );
  44. int visibleCount = 0;
  45. int x = 0;
  46. bool const strip = !tty::out;
  47. while (in != _text.end()) {
  48. char32_t c = *in;
  49. if ('\n' == c || !is_control_code(c)) {
  50. *out = c;
  51. ++out;
  52. ++in;
  53. ++visibleCount;
  54. if ('\n' == c || ++x >= _screenColumns) {
  55. x = 0;
  56. ++_extraLines;
  57. _lastLinePosition = visibleCount;
  58. }
  59. } else if (c == '\x1b') {
  60. if ( strip ) {
  61. // jump over control chars
  62. ++in;
  63. if (*in == '[') {
  64. ++in;
  65. while ( ( in != _text.end() ) && ( ( *in == ';' ) || ( ( ( *in >= '0' ) && ( *in <= '9' ) ) ) ) ) {
  66. ++in;
  67. }
  68. if (*in == 'm') {
  69. ++in;
  70. }
  71. }
  72. } else {
  73. // copy control chars
  74. *out = *in;
  75. ++out;
  76. ++in;
  77. if (*in == '[') {
  78. *out = *in;
  79. ++out;
  80. ++in;
  81. while ( ( in != _text.end() ) && ( ( *in == ';' ) || ( ( ( *in >= '0' ) && ( *in <= '9' ) ) ) ) ) {
  82. *out = *in;
  83. ++out;
  84. ++in;
  85. }
  86. if (*in == 'm') {
  87. *out = *in;
  88. ++out;
  89. ++in;
  90. }
  91. }
  92. }
  93. } else {
  94. ++in;
  95. }
  96. }
  97. _characterCount = visibleCount;
  98. int charCount( static_cast<int>( out - _text.begin() ) );
  99. _text.erase( charCount, _text.length() - charCount );
  100. _cursorRowOffset += _extraLines;
  101. }
  102. int Prompt::indentation() const {
  103. return _characterCount - _lastLinePosition;
  104. }
  105. // Used with DynamicPrompt (history search)
  106. //
  107. const UnicodeString forwardSearchBasePrompt("(i-search)`");
  108. const UnicodeString reverseSearchBasePrompt("(reverse-i-search)`");
  109. const UnicodeString endSearchBasePrompt("': ");
  110. DynamicPrompt::DynamicPrompt( Terminal& terminal_, int initialDirection )
  111. : Prompt( terminal_ )
  112. , _searchText()
  113. , _direction( initialDirection ) {
  114. updateSearchPrompt();
  115. }
  116. void DynamicPrompt::updateSearchPrompt(void) {
  117. update_screen_columns();
  118. const UnicodeString* basePrompt =
  119. (_direction > 0) ? &forwardSearchBasePrompt : &reverseSearchBasePrompt;
  120. _text.assign( *basePrompt ).append( _searchText ).append( endSearchBasePrompt );
  121. update_state();
  122. }
  123. }