選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

history.cxx 3.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. #include <fstream>
  2. #include <cstring>
  3. #ifndef _WIN32
  4. #include <unistd.h>
  5. #include <sys/stat.h>
  6. #endif /* _WIN32 */
  7. #include "history.hxx"
  8. #include "utf8string.hxx"
  9. using namespace std;
  10. namespace replxx {
  11. static int const REPLXX_DEFAULT_HISTORY_MAX_LEN( 1000 );
  12. History::History( void )
  13. : _data()
  14. , _maxSize( REPLXX_DEFAULT_HISTORY_MAX_LEN )
  15. , _maxLineLength( 0 )
  16. , _index( 0 )
  17. , _previousIndex( -2 )
  18. , _recallMostRecent( false ) {
  19. }
  20. void History::add( UnicodeString const& line ) {
  21. if ( ( _maxSize > 0 ) && ( _data.empty() || ( line != _data.back() ) ) ) {
  22. if ( size() > _maxSize ) {
  23. _data.erase( _data.begin() );
  24. if ( -- _previousIndex < -1 ) {
  25. _previousIndex = -2;
  26. }
  27. }
  28. if ( static_cast<int>( line.length() ) > _maxLineLength ) {
  29. _maxLineLength = static_cast<int>( line.length() );
  30. }
  31. _data.push_back( line );
  32. }
  33. }
  34. int History::save( std::string const& filename ) {
  35. #ifndef _WIN32
  36. mode_t old_umask = umask( S_IXUSR | S_IRWXG| S_IRWXO );
  37. #endif
  38. ofstream histFile( filename );
  39. if ( ! histFile ) {
  40. return ( -1 );
  41. }
  42. #ifndef _WIN32
  43. umask( old_umask );
  44. chmod( filename.c_str(), S_IRUSR | S_IWUSR );
  45. #endif
  46. Utf8String utf8;
  47. for ( UnicodeString const& h : _data ) {
  48. if ( ! h.is_empty() ) {
  49. utf8.assign( h );
  50. histFile << utf8.get() << endl;
  51. }
  52. }
  53. return ( 0 );
  54. }
  55. int History::load( std::string const& filename ) {
  56. ifstream histFile( filename );
  57. if ( ! histFile ) {
  58. return ( -1 );
  59. }
  60. string line;
  61. while ( getline( histFile, line ).good() ) {
  62. string::size_type eol( line.find_first_of( "\r\n" ) );
  63. if ( eol != string::npos ) {
  64. line.erase( eol );
  65. }
  66. if ( ! line.empty() ) {
  67. add( UnicodeString( line ) );
  68. }
  69. }
  70. return 0;
  71. }
  72. void History::set_max_size( int size_ ) {
  73. if ( size_ >= 0 ) {
  74. _maxSize = size_;
  75. int curSize( size() );
  76. if ( _maxSize < curSize ) {
  77. _data.erase( _data.begin(), _data.begin() + ( curSize - _maxSize ) );
  78. }
  79. }
  80. }
  81. void History::reset_pos( int pos_ ) {
  82. if ( pos_ == -1 ) {
  83. _index = size() - 1;
  84. _recallMostRecent = false;
  85. } else {
  86. _index = pos_;
  87. }
  88. }
  89. bool History::move( bool up_ ) {
  90. if (_previousIndex != -2 && ! up_ ) {
  91. _index = 1 + _previousIndex; // emulate Windows down-arrow
  92. } else {
  93. _index += up_ ? -1 : 1;
  94. }
  95. _previousIndex = -2;
  96. if (_index < 0) {
  97. _index = 0;
  98. return ( false );
  99. } else if ( _index >= size() ) {
  100. _index = size() - 1;
  101. return ( false );
  102. }
  103. _recallMostRecent = true;
  104. return ( true );
  105. }
  106. void History::jump( bool start_ ) {
  107. _index = start_ ? 0 : size() - 1;
  108. _previousIndex = -2;
  109. _recallMostRecent = true;
  110. }
  111. bool History::common_prefix_search( UnicodeString const& prefix_, int prefixSize_, bool back_ ) {
  112. int direct( size() + ( back_ ? -1 : 1 ) );
  113. int i( ( _index + direct ) % _data.size() );
  114. while ( i != _index ) {
  115. if ( _data[i].starts_with( prefix_.begin(), prefix_.begin() + prefixSize_ ) ) {
  116. _index = i;
  117. _previousIndex = -2;
  118. _recallMostRecent = true;
  119. return ( true );
  120. }
  121. i += direct;
  122. i %= _data.size();
  123. }
  124. return ( false );
  125. }
  126. UnicodeString const& History::operator[] ( int idx_ ) const {
  127. return ( _data[ idx_ ] );
  128. }
  129. }