[Lldb-commits] [lldb] 62bd331 - [LLDB][GUI] Add Environment Variable Field
Greg Clayton via lldb-commits
lldb-commits at lists.llvm.org
Thu Jul 29 13:28:59 PDT 2021
Author: Omar Emara
Date: 2021-07-29T13:28:49-07:00
New Revision: 62bd33158d924f907dfe2ccd250f20ddb8ed09a9
URL: https://github.com/llvm/llvm-project/commit/62bd33158d924f907dfe2ccd250f20ddb8ed09a9
DIFF: https://github.com/llvm/llvm-project/commit/62bd33158d924f907dfe2ccd250f20ddb8ed09a9.diff
LOG: [LLDB][GUI] Add Environment Variable Field
This patch adds an environment variable field. This is usually used as
the basic type of a List field. This is needed to create the process
launch form.
Reviewed By: clayborg
Differential Revision: https://reviews.llvm.org/D106999
Added:
Modified:
lldb/source/Core/IOHandlerCursesGUI.cpp
Removed:
################################################################################
diff --git a/lldb/source/Core/IOHandlerCursesGUI.cpp b/lldb/source/Core/IOHandlerCursesGUI.cpp
index aab5dc9cd8017..010f9300aa2e5 100644
--- a/lldb/source/Core/IOHandlerCursesGUI.cpp
+++ b/lldb/source/Core/IOHandlerCursesGUI.cpp
@@ -1909,6 +1909,176 @@ template <class T> class ListFieldDelegate : public FieldDelegate {
SelectionType m_selection_type;
};
+template <class KeyFieldDelegateType, class ValueFieldDelegateType>
+class MappingFieldDelegate : public FieldDelegate {
+public:
+ MappingFieldDelegate(KeyFieldDelegateType key_field,
+ ValueFieldDelegateType value_field)
+ : m_key_field(key_field), m_value_field(value_field),
+ m_selection_type(SelectionType::Key) {}
+
+ // Signify which element is selected. The key field or its value field.
+ enum class SelectionType { Key, Value };
+
+ // A mapping field is drawn as two text fields with a right arrow in between.
+ // The first field stores the key of the mapping and the second stores the
+ // value if the mapping.
+ //
+ // __[Key]_____________ __[Value]___________
+ // | | > | |
+ // |__________________| |__________________|
+ // - Error message if it exists.
+
+ // The mapping field has a height that is equal to the maximum height between
+ // the key and value fields.
+ int FieldDelegateGetHeight() override {
+ return std::max(m_key_field.FieldDelegateGetHeight(),
+ m_value_field.FieldDelegateGetHeight());
+ }
+
+ void DrawArrow(SubPad &surface) {
+ surface.MoveCursor(0, 1);
+ surface.PutChar(ACS_RARROW);
+ }
+
+ void FieldDelegateDraw(SubPad &surface, bool is_selected) override {
+ Rect bounds = surface.GetFrame();
+ Rect key_field_bounds, arrow_and_value_field_bounds;
+ bounds.VerticalSplit(bounds.size.width / 2, key_field_bounds,
+ arrow_and_value_field_bounds);
+ Rect arrow_bounds, value_field_bounds;
+ arrow_and_value_field_bounds.VerticalSplit(1, arrow_bounds,
+ value_field_bounds);
+
+ SubPad key_field_surface = SubPad(surface, key_field_bounds);
+ SubPad arrow_surface = SubPad(surface, arrow_bounds);
+ SubPad value_field_surface = SubPad(surface, value_field_bounds);
+
+ bool key_is_selected =
+ m_selection_type == SelectionType::Key && is_selected;
+ m_key_field.FieldDelegateDraw(key_field_surface, key_is_selected);
+ DrawArrow(arrow_surface);
+ bool value_is_selected =
+ m_selection_type == SelectionType::Value && is_selected;
+ m_value_field.FieldDelegateDraw(value_field_surface, value_is_selected);
+ }
+
+ HandleCharResult SelectNext(int key) {
+ if (FieldDelegateOnLastOrOnlyElement())
+ return eKeyNotHandled;
+
+ if (!m_key_field.FieldDelegateOnLastOrOnlyElement()) {
+ return m_key_field.FieldDelegateHandleChar(key);
+ }
+
+ m_key_field.FieldDelegateExitCallback();
+ m_selection_type = SelectionType::Value;
+ m_value_field.FieldDelegateSelectFirstElement();
+ return eKeyHandled;
+ }
+
+ HandleCharResult SelectPrevious(int key) {
+ if (FieldDelegateOnFirstOrOnlyElement())
+ return eKeyNotHandled;
+
+ if (!m_value_field.FieldDelegateOnFirstOrOnlyElement()) {
+ return m_value_field.FieldDelegateHandleChar(key);
+ }
+
+ m_value_field.FieldDelegateExitCallback();
+ m_selection_type = SelectionType::Key;
+ m_key_field.FieldDelegateSelectLastElement();
+ return eKeyHandled;
+ }
+
+ HandleCharResult FieldDelegateHandleChar(int key) override {
+ switch (key) {
+ case '\t':
+ SelectNext(key);
+ return eKeyHandled;
+ case KEY_SHIFT_TAB:
+ SelectPrevious(key);
+ return eKeyHandled;
+ default:
+ break;
+ }
+
+ // If the key wasn't handled, pass the key to the selected field.
+ if (m_selection_type == SelectionType::Key)
+ return m_key_field.FieldDelegateHandleChar(key);
+ else
+ return m_value_field.FieldDelegateHandleChar(key);
+
+ return eKeyNotHandled;
+ }
+
+ bool FieldDelegateOnFirstOrOnlyElement() override {
+ return m_selection_type == SelectionType::Key;
+ }
+
+ bool FieldDelegateOnLastOrOnlyElement() override {
+ return m_selection_type == SelectionType::Value;
+ }
+
+ void FieldDelegateSelectFirstElement() override {
+ m_selection_type = SelectionType::Key;
+ }
+
+ void FieldDelegateSelectLastElement() override {
+ m_selection_type = SelectionType::Value;
+ }
+
+ bool FieldDelegateHasError() override {
+ return m_key_field.FieldDelegateHasError() ||
+ m_value_field.FieldDelegateHasError();
+ }
+
+ KeyFieldDelegateType &GetKeyField() { return m_key_field; }
+
+ ValueFieldDelegateType &GetValueField() { return m_value_field; }
+
+protected:
+ KeyFieldDelegateType m_key_field;
+ ValueFieldDelegateType m_value_field;
+ // See SelectionType class enum.
+ SelectionType m_selection_type;
+};
+
+class EnvironmentVariableNameFieldDelegate : public TextFieldDelegate {
+public:
+ EnvironmentVariableNameFieldDelegate(const char *content)
+ : TextFieldDelegate("Name", content, true) {}
+
+ // Environment variable names can't contain an equal sign.
+ bool IsAcceptableChar(int key) override {
+ return TextFieldDelegate::IsAcceptableChar(key) && key != '=';
+ }
+
+ const std::string &GetName() { return m_content; }
+};
+
+class EnvironmentVariableFieldDelegate
+ : public MappingFieldDelegate<EnvironmentVariableNameFieldDelegate,
+ TextFieldDelegate> {
+public:
+ EnvironmentVariableFieldDelegate()
+ : MappingFieldDelegate(
+ EnvironmentVariableNameFieldDelegate(""),
+ TextFieldDelegate("Value", "", /*required=*/false)) {}
+
+ const std::string &GetName() { return GetKeyField().GetName(); }
+
+ const std::string &GetValue() { return GetValueField().GetText(); }
+};
+
+class EnvironmentVariableListFieldDelegate
+ : public ListFieldDelegate<EnvironmentVariableFieldDelegate> {
+public:
+ EnvironmentVariableListFieldDelegate()
+ : ListFieldDelegate("Environment Variables",
+ EnvironmentVariableFieldDelegate()) {}
+};
+
class FormAction {
public:
FormAction(const char *label, std::function<void(Window &)> action)
@@ -2060,6 +2230,36 @@ class FormDelegate {
return delegate;
}
+ template <class K, class V>
+ MappingFieldDelegate<K, V> *AddMappingField(K key_field, V value_field) {
+ MappingFieldDelegate<K, V> *delegate =
+ new MappingFieldDelegate<K, V>(key_field, value_field);
+ m_fields.push_back(FieldDelegateUP(delegate));
+ return delegate;
+ }
+
+ EnvironmentVariableNameFieldDelegate *
+ AddEnvironmentVariableNameField(const char *content) {
+ EnvironmentVariableNameFieldDelegate *delegate =
+ new EnvironmentVariableNameFieldDelegate(content);
+ m_fields.push_back(FieldDelegateUP(delegate));
+ return delegate;
+ }
+
+ EnvironmentVariableFieldDelegate *AddEnvironmentVariableField() {
+ EnvironmentVariableFieldDelegate *delegate =
+ new EnvironmentVariableFieldDelegate();
+ m_fields.push_back(FieldDelegateUP(delegate));
+ return delegate;
+ }
+
+ EnvironmentVariableListFieldDelegate *AddEnvironmentVariableListField() {
+ EnvironmentVariableListFieldDelegate *delegate =
+ new EnvironmentVariableListFieldDelegate();
+ m_fields.push_back(FieldDelegateUP(delegate));
+ return delegate;
+ }
+
// Factory methods for adding actions.
void AddAction(const char *label, std::function<void(Window &)> action) {
More information about the lldb-commits
mailing list