@@ -12,101 +12,60 @@ See the Mulan PSL v2 for more details. */
12
12
// Created by Wangyunlai on 2023/06/25.
13
13
//
14
14
15
- #include < setjmp.h>
16
- #include < signal.h>
15
+ #include < string>
17
16
18
17
#include " net/cli_communicator.h"
19
18
#include " common/lang/string.h"
20
19
#include " common/log/log.h"
21
- #include " common/os/signal.h"
22
20
#include " event/session_event.h"
23
21
#include " net/buffered_writer.h"
24
22
#include " session/session.h"
25
-
26
- #ifdef USE_READLINE
27
- #include " readline/history.h"
28
- #include " readline/readline.h"
29
- #endif
23
+ #include " replxx.hxx"
30
24
31
25
#define MAX_MEM_BUFFER_SIZE 8192
32
26
#define PORT_DEFAULT 6789
33
27
34
28
using namespace common ;
35
29
36
- #ifdef USE_READLINE
37
- const string HISTORY_FILE = string(getenv(" HOME" )) + " /.miniob.history" ;
38
- time_t last_history_write_time = 0 ;
39
- sigjmp_buf ctrlc_buf;
40
- bool ctrlc_flag = false ;
41
-
42
- void handle_signals (int signo) {
43
- if (signo == SIGINT) {
44
- ctrlc_flag = true ;
45
- siglongjmp (ctrlc_buf, 1 );
46
- }
47
- }
30
+ static replxx::Replxx rx;
31
+ const std::string REPLXX_HISTORY_FILE = " ./.miniob.history" ;
32
+ // const int MAX_HISTORY_SIZE = 500; // default: 1000
48
33
49
34
char *my_readline (const char *prompt)
50
35
{
51
- static sighandler_t setup_signal_handler = signal (SIGINT, handle_signals);
52
- (void )setup_signal_handler;
36
+ char const * cinput = nullptr ;
53
37
54
- int size = history_length;
55
- if (size == 0 ) {
56
- read_history (HISTORY_FILE.c_str ());
57
-
58
- FILE *fp = fopen (HISTORY_FILE.c_str (), " a" );
59
- if (fp != nullptr ) {
60
- fclose (fp);
61
- }
38
+ try {
39
+ cinput = rx.input (prompt);
40
+ } catch (std::exception const & e) {
41
+ LOG_WARN (" replxx input error: %s" , e.what ());
42
+ return nullptr ;
62
43
}
63
44
64
- while ( sigsetjmp ( ctrlc_buf, 1 ) != 0 );
65
-
66
- if (ctrlc_flag) {
67
- char *line = (char *)malloc (strlen (" exit" ) + 1 );
68
- strcpy (line, " exit" );
69
- printf (" \n " );
70
- return line;
45
+ if (cinput == nullptr ) {
46
+ return nullptr ;
71
47
}
72
48
73
- char *line = readline (prompt) ;
74
- if (line != nullptr && line[ 0 ] != 0 ) {
75
- add_history (line);
76
- if ( time ( NULL ) - last_history_write_time > 5 ) {
77
- write_history (HISTORY_FILE. c_str ()) ;
49
+ bool is_valid_input = false ;
50
+ for ( auto c = cinput; *c != ' \0 ' ; ++c ) {
51
+ if (! isspace (*c)) {
52
+ is_valid_input = true ;
53
+ break ;
78
54
}
79
- // append_history doesn't work on some readlines
80
- // append_history(1, HISTORY_FILE.c_str());
81
55
}
82
- return line;
83
- }
84
- #else // USE_READLINE
85
- char *my_readline (const char *prompt)
86
- {
87
- char *buffer = (char *)malloc (MAX_MEM_BUFFER_SIZE);
88
- if (nullptr == buffer) {
89
- LOG_WARN (" failed to alloc line buffer" );
90
- return nullptr ;
56
+
57
+ if (is_valid_input) {
58
+ rx.history_add (cinput);
91
59
}
92
- fprintf (stdout, " %s" , prompt);
93
- char *s = fgets (buffer, MAX_MEM_BUFFER_SIZE, stdin);
94
- if (nullptr == s) {
95
- if (ferror (stdin) || feof (stdin)) {
96
- LOG_WARN (" failed to read line: %s" , strerror (errno));
97
- }
98
- /* EINTR(4):Interrupted system call */
99
- if (errno == EINTR) {
100
- strncpy (buffer, " interrupted" , MAX_MEM_BUFFER_SIZE);
101
- fprintf (stdout, " \n " );
102
- return buffer;
103
- }
104
- free (buffer);
105
- return nullptr ;
60
+
61
+ char *line = strdup (cinput);
62
+ if (line == nullptr ) {
63
+ LOG_WARN (" Failed to dup input string from replxx" );
64
+ return nullptr ;
106
65
}
107
- return buffer;
66
+
67
+ return line;
108
68
}
109
- #endif // USE_READLINE
110
69
111
70
/* this function config a exit-cmd list, strncasecmp func truncate the command from terminal according to the number,
112
71
'strncasecmp("exit", cmd, 4)' means that obclient read command string from terminal, truncate it to 4 chars from
@@ -123,7 +82,27 @@ bool is_exit_command(const char *cmd)
123
82
char *read_command ()
124
83
{
125
84
const char *prompt_str = " miniob > " ;
126
- char *input_command = my_readline (prompt_str);
85
+
86
+ static bool is_first_call = true ;
87
+ if (is_first_call) {
88
+ // rx.set_max_history_size(MAX_HISTORY_SIZE);
89
+ // rx.set_unique_history(true);
90
+
91
+ rx.history_load (REPLXX_HISTORY_FILE);
92
+ rx.install_window_change_handler ();
93
+ is_first_call = false ;
94
+ }
95
+
96
+ char *input_command = my_readline (prompt_str);
97
+
98
+ static time_t previous_history_save_time = 0 ;
99
+ if (input_command != nullptr && input_command[0 ] != ' \0 ' ) {
100
+ if (time (NULL ) - previous_history_save_time > 5 ) {
101
+ rx.history_save (REPLXX_HISTORY_FILE);
102
+ previous_history_save_time = time (NULL );
103
+ }
104
+ }
105
+
127
106
return input_command;
128
107
}
129
108
@@ -183,3 +162,9 @@ RC CliCommunicator::write_result(SessionEvent *event, bool &need_disconnect)
183
162
need_disconnect = false ;
184
163
return rc;
185
164
}
165
+
166
+ CliCommunicator::~CliCommunicator ()
167
+ {
168
+ rx.history_save (REPLXX_HISTORY_FILE);
169
+ LOG_INFO (" Command history saved to %s" , REPLXX_HISTORY_FILE.c_str ());
170
+ }
0 commit comments