Skip to content

Commit 2f19b0c

Browse files
Add Arrow Up/Down feature to navigate Command History and Left/Right Arrow to edit command (#136)
* Add command history navigation in user interface Signed-off-by: Lucia Echevarria <luciaechevarria@eprosima.com> * Fix CommandReader and StdinEventHandler tests Signed-off-by: Lucia Echevarria <luciaechevarria@eprosima.com> * Fix Windows compilation Signed-off-by: Lucia Echevarria <luciaechevarria@eprosima.com> * Change getchar() in windows to _getch() Signed-off-by: Denisa <denisa.alexandru@alumnos.upm.es> * Remove tests from windows Signed-off-by: Denisa <denisa@eprosima.com> * Fix uncrustify Signed-off-by: Denisa <denisa@eprosima.com> * Fix storing characters during echo command and fix multiple lines visula bug Signed-off-by: Denisa <denisa@eprosima.com> * Add Left/Right Arrow functionality Signed-off-by: Denisa <denisa@eprosima.com> * Fix uncrustify Signed-off-by: Denisa <denisa@eprosima.com> * Add missing briefs Signed-off-by: Denisa <denisa@eprosima.com> * remove commented lines Signed-off-by: Denisa <denisa@eprosima.com> * Force ANSI enabling in windows Signed-off-by: Denisa <denisa@eprosima.com> * Add function to enale ansi characters in utils.cpp Signed-off-by: Denisa <denisa@eprosima.com> * Fix uncrustify Signed-off-by: Denisa <denisa@eprosima.com> --------- Signed-off-by: Lucia Echevarria <luciaechevarria@eprosima.com> Signed-off-by: Denisa <denisa.alexandru@alumnos.upm.es> Signed-off-by: Denisa <denisa@eprosima.com> Co-authored-by: Lucia Echevarria <luciaechevarria@eprosima.com>
1 parent cbb276e commit 2f19b0c

File tree

11 files changed

+734
-50
lines changed

11 files changed

+734
-50
lines changed

cpp_utils/include/cpp_utils/event/StdinEventHandler.hpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <thread>
2020

2121
#include <cpp_utils/event/EventHandler.hpp>
22+
#include <cpp_utils/history/CommandHistoryHandler.hpp>
2223
#include <cpp_utils/library/library_dll.h>
2324
#include <cpp_utils/time/time_utils.hpp>
2425
#include <cpp_utils/wait/CounterWaitHandler.hpp>
@@ -81,8 +82,35 @@ class StdinEventHandler : public EventHandler<std::string>
8182
CPP_UTILS_DllAPI
8283
void read_one_more_line();
8384

85+
/**
86+
* @brief Temporarily ignore input (disables history addition).
87+
*
88+
* Should be called before an interactive command starts and re-enabled after it finishes.
89+
*/
90+
CPP_UTILS_DllAPI
91+
void set_ignore_input(
92+
bool ignore) noexcept;
93+
94+
/**
95+
* @brief Check whether input is currently being ignored.
96+
*/
97+
CPP_UTILS_DllAPI
98+
bool is_ignoring_input() const noexcept;
99+
84100
protected:
85101

102+
/**
103+
* @brief This function configures the terminal to enable or disable raw input mode.
104+
* When `enable` is `true`, it disables line buffering and input echo
105+
* so that input can be processed character-by-character without displaying typed characters,
106+
* useful for real-time command-line interaction, such as handling arrow keys or passwords.
107+
* When `enable` is `false`, it restores the original terminal settings
108+
* to avoid leaving the terminal in an unusable state.
109+
*/
110+
CPP_UTILS_DllAPI
111+
void set_terminal_mode_(
112+
bool enable) noexcept;
113+
86114
/**
87115
* @brief Internal thread to read from \c source_ .
88116
*
@@ -120,6 +148,8 @@ class StdinEventHandler : public EventHandler<std::string>
120148
//! Counter that contains the number of times the thread is allowed to start waiting for data from source_.
121149
CounterWaitHandler activation_times_;
122150

151+
history::CommandHistoryHandler history_handler_;
152+
123153
/**
124154
* @brief istream source from where to read.
125155
*
@@ -131,6 +161,12 @@ class StdinEventHandler : public EventHandler<std::string>
131161

132162
//! Whether to read whole lines or stop reading in a space.
133163
const bool read_lines_;
164+
165+
private:
166+
167+
//! Whether to ignore input (e.g. during interactive commands like echo)
168+
std::atomic<bool> ignore_input_{false};
169+
134170
};
135171

136172
} /* namespace event */
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#pragma once
16+
17+
#include <string>
18+
#include <vector>
19+
20+
#include <cpp_utils/library/library_dll.h>
21+
22+
namespace eprosima {
23+
namespace utils {
24+
namespace history {
25+
26+
class CommandHistoryHandler
27+
{
28+
public:
29+
30+
/**
31+
* @brief This constructor initializes a CommandHistoryHandler instance,
32+
* setting current_index_ to -1 to indicate that no command in the history is currently selected.
33+
* This is used to manage user input history.
34+
*/
35+
CPP_UTILS_DllAPI
36+
CommandHistoryHandler();
37+
38+
CPP_UTILS_DllAPI
39+
void add_command(
40+
const std::string& command);
41+
42+
CPP_UTILS_DllAPI
43+
std::string get_previous_command();
44+
45+
CPP_UTILS_DllAPI
46+
std::string get_next_command();
47+
48+
private:
49+
50+
std::vector<std::string> command_history_;
51+
52+
size_t current_index_;
53+
};
54+
55+
} /* namespace history */
56+
} /* namespace utils */
57+
} /* namespace eprosima */

cpp_utils/include/cpp_utils/user_interface/CommandReader.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,14 @@ class CommandReader
108108
* value available at a time. But it is the only implementation of ConsumerWaitHandler so far.
109109
*/
110110
event::DBQueueWaitHandler<std::string> commands_read_;
111+
112+
public:
113+
114+
event::StdinEventHandler& stdin_handler()
115+
{
116+
return stdin_handler_;
117+
}
118+
111119
};
112120

113121
} /* namespace utils */

cpp_utils/include/cpp_utils/utils.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ CPP_UTILS_DllAPI
8282
void to_lowercase(
8383
std::string& st) noexcept;
8484

85+
/**
86+
* @brief Enables ANSI escape sequence support for colored output in Windows terminals.
87+
*
88+
* Has no effect on other platforms.
89+
*/
90+
CPP_UTILS_DllAPI
91+
void enable_ansi_colors() noexcept;
92+
8593
/**
8694
* @brief Convert every alphabetic char in string to upper case
8795
*

0 commit comments

Comments
 (0)