summaryrefslogtreecommitdiff
path: root/Libraries/LibLine/LineEditor.h
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-03-31 13:32:11 +0200
committerAndreas Kling <kling@serenityos.org>2020-03-31 13:32:11 +0200
commita30a3277a3c0926a4ae678aa2ba246c2c3cd05eb (patch)
tree918b7786ee52ba858b7b13f6633f9f60d2aafdc3 /Libraries/LibLine/LineEditor.h
parent9c7451a21d876a4be866ab5ae2d3ce2c1beb87c7 (diff)
downloadserenity-a30a3277a3c0926a4ae678aa2ba246c2c3cd05eb.zip
LibLine: Rename from LibLineEdit
Diffstat (limited to 'Libraries/LibLine/LineEditor.h')
-rw-r--r--Libraries/LibLine/LineEditor.h128
1 files changed, 128 insertions, 0 deletions
diff --git a/Libraries/LibLine/LineEditor.h b/Libraries/LibLine/LineEditor.h
new file mode 100644
index 0000000000..8f969658f8
--- /dev/null
+++ b/Libraries/LibLine/LineEditor.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <AK/BinarySearch.h>
+#include <AK/FileSystemPath.h>
+#include <AK/Function.h>
+#include <AK/HashMap.h>
+#include <AK/NonnullOwnPtr.h>
+#include <AK/QuickSort.h>
+#include <AK/String.h>
+#include <AK/Vector.h>
+#include <LibCore/DirIterator.h>
+#include <sys/stat.h>
+#include <termios.h>
+
+class LineEditor;
+
+struct KeyCallback {
+ KeyCallback(Function<bool(LineEditor&)> cb)
+ : callback(move(cb))
+ {
+ }
+ Function<bool(LineEditor&)> callback;
+};
+
+class LineEditor {
+public:
+ LineEditor();
+ ~LineEditor();
+
+ void initialize()
+ {
+ ASSERT(!m_initialized);
+ struct termios termios;
+ tcgetattr(0, &termios);
+ m_default_termios = termios; // grab a copy to restore
+ // Because we use our own line discipline which includes echoing,
+ // we disable ICANON and ECHO.
+ termios.c_lflag &= ~(ECHO | ICANON);
+ tcsetattr(0, TCSANOW, &termios);
+ m_termios = termios;
+ m_initialized = true;
+ }
+
+ String get_line(const String& prompt);
+
+ void add_to_history(const String&);
+ const Vector<String>& history() const { return m_history; }
+
+ void on_char_input(char ch, Function<bool(LineEditor&)> callback);
+
+ Function<Vector<String>(const String&)> on_tab_complete_first_token = nullptr;
+ Function<Vector<String>(const String&)> on_tab_complete_other_token = nullptr;
+
+ // FIXME: we will have to kindly ask our instantiators to set our signal handlers
+ // since we can not do this cleanly ourselves (signal() limitation: cannot give member functions)
+ void interrupted() { m_was_interrupted = true; }
+ void resized() { m_was_resized = true; }
+
+ size_t cursor() const { return m_cursor; }
+ const Vector<char, 1024>& buffer() const { return m_buffer; }
+ char buffer_at(size_t pos) const { return m_buffer.at(pos); }
+
+ void clear_line();
+ void insert(const String&);
+ void insert(const char);
+ void cut_mismatching_chars(String& completion, const String& other, size_t start_compare);
+
+ const struct termios& termios() const { return m_termios; }
+ const struct termios& default_termios() const { return m_default_termios; }
+
+private:
+ void vt_save_cursor();
+ void vt_restore_cursor();
+ void vt_clear_to_end_of_line();
+
+ Vector<char, 1024> m_buffer;
+ size_t m_cursor { 0 };
+ size_t m_times_tab_pressed { 0 };
+ size_t m_num_columns { 0 };
+
+ HashMap<char, NonnullOwnPtr<KeyCallback>> m_key_callbacks;
+
+ // TODO: handle signals internally
+ struct termios m_termios, m_default_termios;
+ bool m_was_interrupted = false;
+ bool m_was_resized = false;
+
+ // FIXME: This should be something more take_first()-friendly.
+ Vector<String> m_history;
+ size_t m_history_cursor { 0 };
+ size_t m_history_capacity { 100 };
+
+ enum class InputState {
+ Free,
+ ExpectBracket,
+ ExpectFinal,
+ ExpectTerminator,
+ };
+ InputState m_state { InputState::Free };
+
+ bool m_initialized = false;
+};