mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 05:27:43 +00:00
LibLine+Shell: Allow some programs to modify the current termios
This setting can be controlled by setting the PROGRAMS_ALLOWED_TO_MODIFY_DEFAULT_TERMIOS _local_ shell variable to a list containing such programs.
This commit is contained in:
parent
e318f12263
commit
b2ef18d538
4 changed files with 50 additions and 11 deletions
|
@ -141,10 +141,6 @@ void Editor::set_default_keybinds()
|
||||||
{
|
{
|
||||||
register_key_input_callback(ctrl('N'), EDITOR_INTERNAL_FUNCTION(search_forwards));
|
register_key_input_callback(ctrl('N'), EDITOR_INTERNAL_FUNCTION(search_forwards));
|
||||||
register_key_input_callback(ctrl('P'), EDITOR_INTERNAL_FUNCTION(search_backwards));
|
register_key_input_callback(ctrl('P'), EDITOR_INTERNAL_FUNCTION(search_backwards));
|
||||||
// Normally ^W. `stty werase \^n` can change it to ^N (or something else), but Serenity doesn't have `stty` yet.
|
|
||||||
register_key_input_callback(m_termios.c_cc[VWERASE], EDITOR_INTERNAL_FUNCTION(erase_word_backwards));
|
|
||||||
// Normally ^U. `stty kill \^n` can change it to ^N (or something else), but Serenity doesn't have `stty` yet.
|
|
||||||
register_key_input_callback(m_termios.c_cc[VKILL], EDITOR_INTERNAL_FUNCTION(kill_line));
|
|
||||||
register_key_input_callback(ctrl('A'), EDITOR_INTERNAL_FUNCTION(go_home));
|
register_key_input_callback(ctrl('A'), EDITOR_INTERNAL_FUNCTION(go_home));
|
||||||
register_key_input_callback(ctrl('B'), EDITOR_INTERNAL_FUNCTION(cursor_left_character));
|
register_key_input_callback(ctrl('B'), EDITOR_INTERNAL_FUNCTION(cursor_left_character));
|
||||||
register_key_input_callback(ctrl('D'), EDITOR_INTERNAL_FUNCTION(erase_character_forwards));
|
register_key_input_callback(ctrl('D'), EDITOR_INTERNAL_FUNCTION(erase_character_forwards));
|
||||||
|
@ -154,7 +150,6 @@ void Editor::set_default_keybinds()
|
||||||
register_key_input_callback(ctrl('H'), EDITOR_INTERNAL_FUNCTION(erase_character_backwards));
|
register_key_input_callback(ctrl('H'), EDITOR_INTERNAL_FUNCTION(erase_character_backwards));
|
||||||
// DEL - Some terminals send this instead of ^H.
|
// DEL - Some terminals send this instead of ^H.
|
||||||
register_key_input_callback((char)127, EDITOR_INTERNAL_FUNCTION(erase_character_backwards));
|
register_key_input_callback((char)127, EDITOR_INTERNAL_FUNCTION(erase_character_backwards));
|
||||||
register_key_input_callback(m_termios.c_cc[VERASE], EDITOR_INTERNAL_FUNCTION(erase_character_backwards));
|
|
||||||
register_key_input_callback(ctrl('K'), EDITOR_INTERNAL_FUNCTION(erase_to_end));
|
register_key_input_callback(ctrl('K'), EDITOR_INTERNAL_FUNCTION(erase_to_end));
|
||||||
register_key_input_callback(ctrl('L'), EDITOR_INTERNAL_FUNCTION(clear_screen));
|
register_key_input_callback(ctrl('L'), EDITOR_INTERNAL_FUNCTION(clear_screen));
|
||||||
register_key_input_callback(ctrl('R'), EDITOR_INTERNAL_FUNCTION(enter_search));
|
register_key_input_callback(ctrl('R'), EDITOR_INTERNAL_FUNCTION(enter_search));
|
||||||
|
@ -175,6 +170,13 @@ void Editor::set_default_keybinds()
|
||||||
register_key_input_callback(Key { 'l', Key::Alt }, EDITOR_INTERNAL_FUNCTION(lowercase_word));
|
register_key_input_callback(Key { 'l', Key::Alt }, EDITOR_INTERNAL_FUNCTION(lowercase_word));
|
||||||
register_key_input_callback(Key { 'u', Key::Alt }, EDITOR_INTERNAL_FUNCTION(uppercase_word));
|
register_key_input_callback(Key { 'u', Key::Alt }, EDITOR_INTERNAL_FUNCTION(uppercase_word));
|
||||||
register_key_input_callback(Key { 't', Key::Alt }, EDITOR_INTERNAL_FUNCTION(transpose_words));
|
register_key_input_callback(Key { 't', Key::Alt }, EDITOR_INTERNAL_FUNCTION(transpose_words));
|
||||||
|
|
||||||
|
// Register these last to all the user to override the previous key bindings
|
||||||
|
// Normally ^W. `stty werase \^n` can change it to ^N (or something else).
|
||||||
|
register_key_input_callback(m_termios.c_cc[VWERASE], EDITOR_INTERNAL_FUNCTION(erase_word_backwards));
|
||||||
|
// Normally ^U. `stty kill \^n` can change it to ^N (or something else).
|
||||||
|
register_key_input_callback(m_termios.c_cc[VKILL], EDITOR_INTERNAL_FUNCTION(kill_line));
|
||||||
|
register_key_input_callback(m_termios.c_cc[VERASE], EDITOR_INTERNAL_FUNCTION(erase_character_backwards));
|
||||||
}
|
}
|
||||||
|
|
||||||
Editor::Editor(Configuration configuration)
|
Editor::Editor(Configuration configuration)
|
||||||
|
@ -552,6 +554,16 @@ void Editor::initialize()
|
||||||
m_initialized = true;
|
m_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Editor::refetch_default_termios()
|
||||||
|
{
|
||||||
|
struct termios termios;
|
||||||
|
tcgetattr(0, &termios);
|
||||||
|
m_default_termios = termios;
|
||||||
|
if (m_configuration.operation_mode == Configuration::Full)
|
||||||
|
termios.c_lflag &= ~(ECHO | ICANON);
|
||||||
|
m_termios = termios;
|
||||||
|
}
|
||||||
|
|
||||||
void Editor::interrupted()
|
void Editor::interrupted()
|
||||||
{
|
{
|
||||||
if (m_is_searching)
|
if (m_is_searching)
|
||||||
|
|
|
@ -148,6 +148,8 @@ public:
|
||||||
|
|
||||||
void initialize();
|
void initialize();
|
||||||
|
|
||||||
|
void refetch_default_termios();
|
||||||
|
|
||||||
void add_to_history(const String& line);
|
void add_to_history(const String& line);
|
||||||
bool load_history(const String& path);
|
bool load_history(const String& path);
|
||||||
bool save_history(const String& path);
|
bool save_history(const String& path);
|
||||||
|
|
|
@ -342,7 +342,7 @@ Shell::LocalFrame* Shell::find_frame_containing_local_variable(const String& nam
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<AST::Value> Shell::lookup_local_variable(const String& name)
|
RefPtr<AST::Value> Shell::lookup_local_variable(const String& name) const
|
||||||
{
|
{
|
||||||
if (auto* frame = find_frame_containing_local_variable(name))
|
if (auto* frame = find_frame_containing_local_variable(name))
|
||||||
return frame->local_variables.get(name).value();
|
return frame->local_variables.get(name).value();
|
||||||
|
@ -353,7 +353,7 @@ RefPtr<AST::Value> Shell::lookup_local_variable(const String& name)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<AST::Value> Shell::get_argument(size_t index)
|
RefPtr<AST::Value> Shell::get_argument(size_t index) const
|
||||||
{
|
{
|
||||||
if (index == 0)
|
if (index == 0)
|
||||||
return adopt_ref(*new AST::StringValue(current_script));
|
return adopt_ref(*new AST::StringValue(current_script));
|
||||||
|
@ -377,7 +377,7 @@ RefPtr<AST::Value> Shell::get_argument(size_t index)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
String Shell::local_variable_or(const String& name, const String& replacement)
|
String Shell::local_variable_or(const String& name, const String& replacement) const
|
||||||
{
|
{
|
||||||
auto value = lookup_local_variable(name);
|
auto value = lookup_local_variable(name);
|
||||||
if (value) {
|
if (value) {
|
||||||
|
@ -846,6 +846,12 @@ RefPtr<Job> Shell::run_command(const AST::Command& command)
|
||||||
last_return_code = job->exit_code();
|
last_return_code = job->exit_code();
|
||||||
job->disown();
|
job->disown();
|
||||||
|
|
||||||
|
if (m_editor && job->exit_code() == 0 && is_allowed_to_modify_termios(job->command())) {
|
||||||
|
m_editor->refetch_default_termios();
|
||||||
|
default_termios = m_editor->default_termios();
|
||||||
|
termios = m_editor->termios();
|
||||||
|
}
|
||||||
|
|
||||||
run_tail(job);
|
run_tail(job);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1025,6 +1031,19 @@ bool Shell::run_file(const String& filename, bool explicitly_invoked)
|
||||||
auto data = file->read_all();
|
auto data = file->read_all();
|
||||||
return run_command(data) == 0;
|
return run_command(data) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Shell::is_allowed_to_modify_termios(const AST::Command& command) const
|
||||||
|
{
|
||||||
|
if (command.argv.is_empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto value = lookup_local_variable("PROGRAMS_ALLOWED_TO_MODIFY_DEFAULT_TERMIOS"sv);
|
||||||
|
if (!value)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return value->resolve_as_list(*this).contains_slow(command.argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
void Shell::restore_ios()
|
void Shell::restore_ios()
|
||||||
{
|
{
|
||||||
if (m_is_subshell)
|
if (m_is_subshell)
|
||||||
|
|
|
@ -108,9 +108,9 @@ public:
|
||||||
|
|
||||||
static bool has_history_event(StringView);
|
static bool has_history_event(StringView);
|
||||||
|
|
||||||
RefPtr<AST::Value> get_argument(size_t);
|
RefPtr<AST::Value> get_argument(size_t) const;
|
||||||
RefPtr<AST::Value> lookup_local_variable(const String&);
|
RefPtr<AST::Value> lookup_local_variable(const String&) const;
|
||||||
String local_variable_or(const String&, const String&);
|
String local_variable_or(const String&, const String&) const;
|
||||||
void set_local_variable(const String&, RefPtr<AST::Value>, bool only_in_current_frame = false);
|
void set_local_variable(const String&, RefPtr<AST::Value>, bool only_in_current_frame = false);
|
||||||
void unset_local_variable(const String&, bool only_in_current_frame = false);
|
void unset_local_variable(const String&, bool only_in_current_frame = false);
|
||||||
|
|
||||||
|
@ -278,6 +278,8 @@ private:
|
||||||
|
|
||||||
void timer_event(Core::TimerEvent&) override;
|
void timer_event(Core::TimerEvent&) override;
|
||||||
|
|
||||||
|
bool is_allowed_to_modify_termios(const AST::Command&) const;
|
||||||
|
|
||||||
// FIXME: Port to Core::Property
|
// FIXME: Port to Core::Property
|
||||||
void save_to(JsonObject&);
|
void save_to(JsonObject&);
|
||||||
void bring_cursor_to_beginning_of_a_line() const;
|
void bring_cursor_to_beginning_of_a_line() const;
|
||||||
|
@ -288,6 +290,10 @@ private:
|
||||||
void stop_all_jobs();
|
void stop_all_jobs();
|
||||||
const Job* m_current_job { nullptr };
|
const Job* m_current_job { nullptr };
|
||||||
LocalFrame* find_frame_containing_local_variable(const String& name);
|
LocalFrame* find_frame_containing_local_variable(const String& name);
|
||||||
|
const LocalFrame* find_frame_containing_local_variable(const String& name) const
|
||||||
|
{
|
||||||
|
return const_cast<Shell*>(this)->find_frame_containing_local_variable(name);
|
||||||
|
}
|
||||||
|
|
||||||
void run_tail(RefPtr<Job>);
|
void run_tail(RefPtr<Job>);
|
||||||
void run_tail(const AST::Command&, const AST::NodeWithAction&, int head_exit_code);
|
void run_tail(const AST::Command&, const AST::NodeWithAction&, int head_exit_code);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue