Refactor source view states to use base class and fix open-files start path
- Add SourceViewsBaseState inheritance to Command, Insert, MultiInsert, and ReadOnly states - Extract common focus_in_event logic to base class - Fix open-files command to use current file's directory as file picker start path - Extract modifier key state logic into reusable get_modkeys_states() method - Pass modifier keys to command exec_with_args in key_press_event - Add type hints to key_mapper methods
This commit is contained in:
3
plugins/code/autopairs/__init__.py
Normal file
3
plugins/code/autopairs/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Plugin Module
|
||||
"""
|
||||
3
plugins/code/autopairs/__main__.py
Normal file
3
plugins/code/autopairs/__main__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Plugin Package
|
||||
"""
|
||||
97
plugins/code/autopairs/autopairs.py
Normal file
97
plugins/code/autopairs/autopairs.py
Normal file
@@ -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
|
||||
7
plugins/code/autopairs/manifest.json
Normal file
7
plugins/code/autopairs/manifest.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "Autopairs",
|
||||
"author": "ITDominator",
|
||||
"version": "0.0.1",
|
||||
"support": "",
|
||||
"requests": {}
|
||||
}
|
||||
55
plugins/code/autopairs/plugin.py
Normal file
55
plugins/code/autopairs/plugin.py
Normal file
@@ -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 = [
|
||||
"'", "`", "[", "]",
|
||||
'<Shift>"',
|
||||
'<Shift>(',
|
||||
'<Shift>)',
|
||||
'<Shift>{',
|
||||
'<Shift>}'
|
||||
]
|
||||
)
|
||||
|
||||
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)
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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) )
|
||||
|
||||
Reference in New Issue
Block a user