diff --git a/plugins/code/autopairs/__init__.py b/plugins/code/autopairs/__init__.py new file mode 100644 index 0000000..e6b1b36 --- /dev/null +++ b/plugins/code/autopairs/__init__.py @@ -0,0 +1,3 @@ +""" + Plugin Module +""" diff --git a/plugins/code/autopairs/__main__.py b/plugins/code/autopairs/__main__.py new file mode 100644 index 0000000..c2e27a7 --- /dev/null +++ b/plugins/code/autopairs/__main__.py @@ -0,0 +1,3 @@ +""" + Plugin Package +""" diff --git a/plugins/code/autopairs/autopairs.py b/plugins/code/autopairs/autopairs.py new file mode 100644 index 0000000..221393a --- /dev/null +++ b/plugins/code/autopairs/autopairs.py @@ -0,0 +1,97 @@ +# Python imports + +# Lib imports + +# Application imports + + + +class Autopairs: + def __init__(self): + ... + + def handle_word_wrap(self, buffer, char_str: str): + wrap_block = self.get_wrap_block(char_str) + if not wrap_block: return + + selection = buffer.get_selection_bounds() + if not selection: + self.insert_pair(buffer, char_str, wrap_block) + return True + + self.wrap_selection(buffer, char_str, wrap_block, selection) + + return True + + def insert_pair( + self, buffer, char_str: str, wrap_block: tuple + ): + buffer.begin_user_action() + + left_block, right_block = wrap_block + insert_mark = buffer.get_insert() + + insert_itr = buffer.get_iter_at_mark(insert_mark) + buffer.insert(insert_itr, f"{left_block}{right_block}") + insert_itr = buffer.get_iter_at_mark( insert_mark ) + insert_itr.backward_char() + + buffer.place_cursor(insert_itr) + + buffer.end_user_action() + + def wrap_selection( + self, buffer, char_str: str, wrap_block: tuple, selection + ): + left_block, \ + right_block = wrap_block + start_itr, \ + end_itr = selection + data = buffer.get_text( + start_itr, end_itr, include_hidden_chars = False + ) + start_mark = buffer.create_mark("startclose", start_itr, False) + end_mark = buffer.create_mark("endclose", end_itr, True) + + buffer.begin_user_action() + + buffer.insert(start_itr, left_block) + end_itr = buffer.get_iter_at_mark(end_mark) + buffer.insert(end_itr, right_block) + + start = buffer.get_iter_at_mark(start_mark) + end = buffer.get_iter_at_mark(end_mark) + + buffer.select_range(start, end) + buffer.delete_mark_by_name("startclose") + buffer.delete_mark_by_name("endclose") + + buffer.end_user_action() + + def get_wrap_block(self, char_str) -> tuple: + left_block = "" + right_block = "" + + match char_str: + case "(" | ")": + left_block = "(" + right_block = ")" + case "[" | "]": + left_block = "[" + right_block = "]" + case "{" | "}": + left_block = "{" + right_block = "}" + case '"': + left_block = '"' + right_block = '"' + case "'": + left_block = "'" + right_block = "'" + case "`": + left_block = "`" + right_block = "`" + case _: + return () + + return left_block, right_block diff --git a/plugins/code/autopairs/manifest.json b/plugins/code/autopairs/manifest.json new file mode 100644 index 0000000..0df9082 --- /dev/null +++ b/plugins/code/autopairs/manifest.json @@ -0,0 +1,7 @@ +{ + "name": "Autopairs", + "author": "ITDominator", + "version": "0.0.1", + "support": "", + "requests": {} +} diff --git a/plugins/code/autopairs/plugin.py b/plugins/code/autopairs/plugin.py new file mode 100644 index 0000000..164500c --- /dev/null +++ b/plugins/code/autopairs/plugin.py @@ -0,0 +1,55 @@ +# Python imports + +# Lib imports + +# Application imports +from libs.event_factory import Event_Factory, Code_Event_Types + +from plugins.plugin_types import PluginCode + +from .autopairs import Autopairs + + + +autopairs = Autopairs() + + + +class Plugin(PluginCode): + def __init__(self): + super(Plugin, self).__init__() + + def _controller_message(self, event: Code_Event_Types.CodeEvent): + ... + + def load(self): + event = Event_Factory.create_event("register_command", + command_name = "autopairs", + command = Handler, + binding_mode = "held", + binding = [ + "'", "`", "[", "]", + '"', + '(', + ')', + '{', + '}' + ] + ) + + self.message_to("source_views", event) + + def run(self): + ... + + +class Handler: + @staticmethod + def execute( + view: any, + char_str: str, + *args, + **kwargs + ): + logger.debug("Command: Autopairs") + autopairs.handle_word_wrap(view.get_buffer(), char_str) diff --git a/src/core/widgets/code/command_system/commands/open_files.py b/src/core/widgets/code/command_system/commands/open_files.py index d318589..e5fb83d 100644 --- a/src/core/widgets/code/command_system/commands/open_files.py +++ b/src/core/widgets/code/command_system/commands/open_files.py @@ -18,10 +18,14 @@ def execute( **kwargs ): logger.debug("Command: Open File(s)") - gfiles = event_system.emit_and_await("open-files") + file = view.command.get_file(view) + start_path = None + if not file.ftype == "buffer": + start_path = file.get_location() + + gfiles = event_system.emit_and_await("open-files", (None, None, start_path)) if not gfiles: return - file = view.command.get_file(view) if file.ftype == "buffer": gfile = gfiles.pop() view.command.exec_with_args("load_file", view, gfile, file) diff --git a/src/core/widgets/code/controllers/views/states/source_view_base_state.py b/src/core/widgets/code/controllers/views/states/source_view_base_state.py new file mode 100644 index 0000000..72cbbfe --- /dev/null +++ b/src/core/widgets/code/controllers/views/states/source_view_base_state.py @@ -0,0 +1,80 @@ +# Python imports + +# Lib imports + +# Application imports +from libs.event_factory import Event_Factory, Code_Event_Types + +from libs.dto.states import SourceViewStates + + + +class SourceViewsBaseState: + def __init__(self): + super(SourceViewsBaseState, self).__init__() + + + def focus_in_event(self, source_view, eve, emit): + source_view.command.exec("set_miniview") + source_view.command.exec("set_focus_border") + source_view.command.exec("update_info_bar") + + event = Event_Factory.create_event("focused_view", view = source_view) + emit(event) + + def insert_text(self, file, text: str): + + return True + + def move_cursor(self, source_view, step, count, extend_selection, emit): + buffer = source_view.get_buffer() + itr = buffer.get_iter_at_mark( buffer.get_insert() ) + line = itr.get_line() + char = itr.get_line_offset() + event = Event_Factory.create_event( + "cursor_moved", + view = source_view, + buffer = buffer, + line = line, + char = char + ) + + emit(event) + + source_view.command.exec("update_info_bar") + + def button_press_event(self, source_view, eve): + source_view.command.exec("update_info_bar") + + def button_release_event(self, source_view, eve): + source_view.command.exec("update_info_bar") + + def key_press_event(self, source_view, eve, key_mapper): + command = key_mapper._key_press_event(eve) + is_future = key_mapper._key_release_event(eve) + char_str = key_mapper.get_char(eve) + modkeys_states = key_mapper.get_modkeys_states(eve) + + if is_future: return True + if not command: return False + + response = source_view.command.exec_with_args( + command, source_view, char_str, modkeys_states + ) + + return True if not response else response + + def key_release_event(self, source_view, eve, key_mapper): + command = key_mapper._key_release_event(eve) + is_past = key_mapper._key_press_event(eve) + char_str = key_mapper.get_char(eve) + modkeys_states = key_mapper.get_modkeys_states(eve) + + if is_past: return True + if not command: return False + + response = source_view.command.exec_with_args( + command, source_view, char_str, modkeys_states + ) + + return True if not response else response diff --git a/src/core/widgets/code/controllers/views/states/source_view_command_state.py b/src/core/widgets/code/controllers/views/states/source_view_command_state.py index d57d808..9042270 100644 --- a/src/core/widgets/code/controllers/views/states/source_view_command_state.py +++ b/src/core/widgets/code/controllers/views/states/source_view_command_state.py @@ -7,9 +7,11 @@ from libs.event_factory import Event_Factory, Code_Event_Types from libs.dto.states import SourceViewStates +from .source_view_base_state import SourceViewsBaseState -class SourceViewsCommandState: + +class SourceViewsCommandState(SourceViewsBaseState): def __init__(self): super(SourceViewsCommandState, self).__init__() @@ -17,10 +19,10 @@ class SourceViewsCommandState: def focus_in_event(self, source_view, eve, emit): return True - def move_cursor(self, source_view, step, count, extend_selection, emit): + def insert_text(self, file, text): return True - def insert_text(self, file, text): + def move_cursor(self, source_view, step, count, extend_selection, emit): return True def button_press_event(self, source_view, eve): diff --git a/src/core/widgets/code/controllers/views/states/source_view_insert_state.py b/src/core/widgets/code/controllers/views/states/source_view_insert_state.py index d75b577..6ce341b 100644 --- a/src/core/widgets/code/controllers/views/states/source_view_insert_state.py +++ b/src/core/widgets/code/controllers/views/states/source_view_insert_state.py @@ -7,68 +7,10 @@ from libs.event_factory import Event_Factory, Code_Event_Types from libs.dto.states import SourceViewStates +from .source_view_base_state import SourceViewsBaseState -class SourceViewsInsertState: + +class SourceViewsInsertState(SourceViewsBaseState): def __init__(self): super(SourceViewsInsertState, self).__init__() - - - def focus_in_event(self, source_view, eve, emit): - source_view.command.exec("set_miniview") - source_view.command.exec("set_focus_border") - source_view.command.exec("update_info_bar") - - event = Event_Factory.create_event("focused_view", view = source_view) - emit(event) - - def insert_text(self, file, text: str): - - return True - - def move_cursor(self, source_view, step, count, extend_selection, emit): - buffer = source_view.get_buffer() - itr = buffer.get_iter_at_mark( buffer.get_insert() ) - line = itr.get_line() - char = itr.get_line_offset() - event = Event_Factory.create_event( - "cursor_moved", - view = source_view, - buffer = buffer, - line = line, - char = char - ) - - emit(event) - - source_view.command.exec("update_info_bar") - - def button_press_event(self, source_view, eve): - source_view.command.exec("update_info_bar") - - def button_release_event(self, source_view, eve): - source_view.command.exec("update_info_bar") - - def key_press_event(self, source_view, eve, key_mapper): - command = key_mapper._key_press_event(eve) - is_future = key_mapper._key_release_event(eve) - char_str = key_mapper.get_char(eve) - - if is_future: return True - if not command: return False - - source_view.command.exec_with_args(command, source_view, char_str) - - return True - - def key_release_event(self, source_view, eve, key_mapper): - command = key_mapper._key_release_event(eve) - is_past = key_mapper._key_press_event(eve) - char_str = key_mapper.get_char(eve) - - if is_past: return True - if not command: return False - - source_view.command.exec_with_args(command, source_view, char_str) - - return True diff --git a/src/core/widgets/code/controllers/views/states/source_view_multi_insert_state.py b/src/core/widgets/code/controllers/views/states/source_view_multi_insert_state.py index 2429fb9..8f9babd 100644 --- a/src/core/widgets/code/controllers/views/states/source_view_multi_insert_state.py +++ b/src/core/widgets/code/controllers/views/states/source_view_multi_insert_state.py @@ -11,9 +11,11 @@ from libs.dto.states import SourceViewStates, MoveDirection, CursorAction from ....mixins.source_mark_events_mixin import MarkEventsMixin +from .source_view_base_state import SourceViewsBaseState -class SourceViewsMultiInsertState(MarkEventsMixin): + +class SourceViewsMultiInsertState(SourceViewsBaseState, MarkEventsMixin): def __init__(self): super(SourceViewsMultiInsertState, self).__init__() @@ -22,14 +24,6 @@ class SourceViewsMultiInsertState(MarkEventsMixin): self.insert_markers: list = [] - def focus_in_event(self, source_view, eve, emit): - source_view.command.exec("set_miniview") - source_view.command.exec("set_focus_border") - source_view.command.exec("update_info_bar") - - event = Event_Factory.create_event("focused_view", view = source_view) - emit(event) - def insert_text(self, file, text): if not self.insert_markers: return False @@ -86,7 +80,7 @@ class SourceViewsMultiInsertState(MarkEventsMixin): source_view.command.exec("update_info_bar") def button_press_event(self, source_view, eve): - source_view.command.exec("update_info_bar") + super().button_press_event(source_view, eve) return True def button_release_event(self, source_view, eve): @@ -129,20 +123,13 @@ class SourceViewsMultiInsertState(MarkEventsMixin): command = key_mapper._key_press_event(eve) if not command: return False - source_view.command.exec(command) + char_str = key_mapper.get_char(eve) + modkeys_states = key_mapper.get_modkeys_states(eve) + response = source_view.command.exec_with_args( + command, source_view, char_str, modkeys_states + ) - return True - - def key_release_event(self, source_view, eve, key_mapper): - command = key_mapper._key_release_event(eve) - is_past = key_mapper._key_press_event(eve) - - if is_past: return True - if not command: return False - - source_view.command.exec(command) - - return True + return True if not response else response def _signal_cursor_moved(self, source_view, emit): buffer = source_view.get_buffer() diff --git a/src/core/widgets/code/controllers/views/states/source_view_read_only_state.py b/src/core/widgets/code/controllers/views/states/source_view_read_only_state.py index 07317d2..0a2aaf0 100644 --- a/src/core/widgets/code/controllers/views/states/source_view_read_only_state.py +++ b/src/core/widgets/code/controllers/views/states/source_view_read_only_state.py @@ -7,9 +7,11 @@ from libs.event_factory import Event_Factory, Code_Event_Types from libs.dto.states import SourceViewStates +from .source_view_base_state import SourceViewsBaseState -class SourceViewsReadOnlyState: + +class SourceViewsReadOnlyState(SourceViewsBaseState): def __init__(self): super(SourceViewsReadOnlyState, self).__init__() @@ -17,10 +19,10 @@ class SourceViewsReadOnlyState: def focus_in_event(self, source_view, eve, emit): return True - def move_cursor(self, source_view, step, count, extend_selection, emit): + def insert_text(self, file, text): return True - def insert_text(self, file, text): + def move_cursor(self, source_view, step, count, extend_selection, emit): return True def button_press_event(self, source_view, eve): diff --git a/src/core/widgets/code/key_mapper.py b/src/core/widgets/code/key_mapper.py index 0fae401..eb1b473 100644 --- a/src/core/widgets/code/key_mapper.py +++ b/src/core/widgets/code/key_mapper.py @@ -119,14 +119,9 @@ class KeyMapper: return self.states[self.state].released[char_str] def _set_key_state(self, eve): - modifiers = Gdk.ModifierType(eve.get_state() & ~Gdk.ModifierType.LOCK_MASK) - is_control = modifiers & Gdk.ModifierType.CONTROL_MASK - is_shift = modifiers & Gdk.ModifierType.SHIFT_MASK - - try: - is_alt = modifiers & Gdk.ModifierType.ALT_MASK - except: - is_alt = modifiers & Gdk.ModifierType.MOD1_MASK + is_control, \ + is_shift, \ + is_alt = self.get_modkeys_states(eve) self.state = NoKeyState if is_control: @@ -144,11 +139,23 @@ class KeyMapper: modifiers = Gdk.ModifierType(eve.get_state() & ~Gdk.ModifierType.LOCK_MASK) return modifiers & Gdk.ModifierType.SHIFT_MASK - def get_raw_keyname(self, eve): + def get_raw_keyname(self, eve) -> str: return Gdk.keyval_name(eve.keyval) - def get_keyname(self, eve): + def get_modkeys_states(self, eve) -> tuple: + modifiers = Gdk.ModifierType(eve.get_state() & ~Gdk.ModifierType.LOCK_MASK) + is_control = modifiers & Gdk.ModifierType.CONTROL_MASK + is_shift = modifiers & Gdk.ModifierType.SHIFT_MASK + + try: + is_alt = modifiers & Gdk.ModifierType.ALT_MASK + except: + is_alt = modifiers & Gdk.ModifierType.MOD1_MASK + + return is_control, is_shift, is_alt + + def get_keyname(self, eve) -> str: return Gdk.keyval_name(eve.keyval).lower() - def get_char(self, eve): + def get_char(self, eve) -> str: return chr( Gdk.keyval_to_unicode(eve.keyval) )