develop #3
@@ -8,6 +8,7 @@ gi.require_version('GtkSource', '4')
|
||||
from gi.repository import GtkSource
|
||||
|
||||
# Application imports
|
||||
from libs.dto.states import SourceViewStates
|
||||
|
||||
|
||||
|
||||
@@ -17,4 +18,6 @@ def execute(
|
||||
**kwargs
|
||||
):
|
||||
logger.debug("Command: Line Down")
|
||||
if not view.state == SourceViewStates.INSERT: return
|
||||
|
||||
view.emit("move-lines", True)
|
||||
|
||||
@@ -8,6 +8,7 @@ gi.require_version('GtkSource', '4')
|
||||
from gi.repository import GtkSource
|
||||
|
||||
# Application imports
|
||||
from libs.dto.states import SourceViewStates
|
||||
|
||||
|
||||
|
||||
@@ -17,4 +18,6 @@ def execute(
|
||||
**kwargs
|
||||
):
|
||||
logger.debug("Command: Line Up")
|
||||
if not view.state == SourceViewStates.INSERT: return
|
||||
|
||||
view.emit("move-lines", False)
|
||||
|
||||
@@ -56,10 +56,28 @@ class MarkerManager(MarkSupportMixin):
|
||||
continue
|
||||
|
||||
if has_selection:
|
||||
caret_itr = buffer.get_iter_at_mark(end_mark)
|
||||
start_itr = buffer.get_iter_at_mark(start_mark)
|
||||
is_left_edge = caret_itr.compare(start_itr) <= 0
|
||||
is_right_edge = not is_left_edge
|
||||
can_move = (
|
||||
(is_forward and is_right_edge) or
|
||||
(not is_forward and is_left_edge)
|
||||
)
|
||||
|
||||
self.collapse_selection(buffer, mark_hash, start_mark, end_mark, is_forward)
|
||||
if mode == "word":
|
||||
if not can_move: continue
|
||||
|
||||
itr = caret_itr
|
||||
self._move_iter(buffer, itr, mode, is_forward)
|
||||
buffer.move_mark(start_mark, itr)
|
||||
buffer.move_mark(end_mark, itr)
|
||||
|
||||
continue
|
||||
|
||||
# No selection — move both anchor and caret together
|
||||
|
||||
# No selection - move both anchor and caret together
|
||||
self._move_iter(buffer, end_itr, mode, is_forward)
|
||||
|
||||
buffer.move_mark(start_mark, end_itr)
|
||||
@@ -81,17 +99,50 @@ class MarkerManager(MarkSupportMixin):
|
||||
left = end_itr
|
||||
right = start_itr
|
||||
|
||||
# If moving forward → collapse to right edge
|
||||
# If moving forward -> collapse to right edge
|
||||
collapse_itr = right if is_forward else left
|
||||
|
||||
buffer.move_mark(start_mark, collapse_itr)
|
||||
buffer.move_mark(end_mark, collapse_itr)
|
||||
|
||||
def move_word_snake_case(self, itr: Gtk.TextIter, count: int):
|
||||
def is_word(ch):
|
||||
return ch and (ch.isalnum() or ch == "_")
|
||||
|
||||
def step(fwd):
|
||||
return itr.forward_cursor_position() if fwd else itr.backward_cursor_position()
|
||||
|
||||
def peek(fwd):
|
||||
if fwd: return itr.get_char()
|
||||
tmp = itr.copy()
|
||||
return tmp.backward_cursor_position() and tmp.get_char()
|
||||
|
||||
def walk(fwd, cond):
|
||||
while True:
|
||||
ch = peek(fwd)
|
||||
if not cond(ch): break
|
||||
if not step(fwd): return False
|
||||
|
||||
return True
|
||||
|
||||
fwd = count > 0
|
||||
|
||||
for _ in range(abs(count)):
|
||||
ch = itr.get_char() if fwd else peek(False)
|
||||
|
||||
if is_word(ch):
|
||||
# inside word
|
||||
if not walk(fwd, is_word): return
|
||||
else:
|
||||
# in separators -> skip them, then the word
|
||||
if not walk(fwd, lambda c: not is_word(c)): return
|
||||
if not walk(fwd, is_word): return
|
||||
|
||||
def _move_iter(self, buffer, itr_, mode: str, is_forward: bool):
|
||||
if mode == "char":
|
||||
itr_.forward_char() if is_forward else itr_.backward_char()
|
||||
elif mode == "word":
|
||||
itr_.forward_word_end() if is_forward else itr_.backward_word_start()
|
||||
self.move_word_snake_case(itr_, 1 if is_forward else -1)
|
||||
elif mode == "line":
|
||||
line = itr_.get_line()
|
||||
offset = itr_.get_line_offset()
|
||||
|
||||
@@ -57,6 +57,7 @@ class SourceViewSignalMapper:
|
||||
"key-release-event": self._key_release_event,
|
||||
"button-press-event": self._button_press_event,
|
||||
"button-release-event": self._button_release_event,
|
||||
"scroll-event": self._scroll_event,
|
||||
"populate-popup": self._populate_popup
|
||||
}
|
||||
|
||||
@@ -81,5 +82,8 @@ class SourceViewSignalMapper:
|
||||
def _button_release_event(self, source_view: SourceView, eve):
|
||||
return self.state_manager.handle_button_release_event(source_view, eve)
|
||||
|
||||
def _populate_popup(self, source_view, menu):
|
||||
def _scroll_event(self, source_view: SourceView, eve):
|
||||
return self.state_manager.handle_scroll_event(source_view, eve)
|
||||
|
||||
def _populate_popup(self, source_view: SourceView, menu):
|
||||
return self.state_manager.handle_populate_popup(source_view, menu, self.emit)
|
||||
|
||||
@@ -53,8 +53,15 @@ class SourceViewStateManager:
|
||||
def handle_button_release_event(self, source_view, eve):
|
||||
return self.states[source_view.state].button_release_event(source_view, eve)
|
||||
|
||||
def handle_scroll_event(self, source_view, eve):
|
||||
return self.states[source_view.state].scroll_event(
|
||||
source_view, eve, self.key_mapper
|
||||
)
|
||||
|
||||
def handle_populate_popup(self, source_view, menu, emit):
|
||||
return self.states[source_view.state].populate_popup(source_view, menu, emit)
|
||||
return self.states[source_view.state].populate_popup(
|
||||
source_view, menu, emit
|
||||
)
|
||||
|
||||
def _handle_multi_insert_toggle(self, source_view, eve):
|
||||
is_control = self.key_mapper.is_control(eve)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gdk', '3.0')
|
||||
from gi.repository import Gdk
|
||||
|
||||
# Application imports
|
||||
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||
@@ -79,6 +82,29 @@ class SourceViewsBaseState:
|
||||
|
||||
return True if not response else response
|
||||
|
||||
def scroll_event(self, source_view, eve, key_mapper):
|
||||
is_control = key_mapper.is_control(eve)
|
||||
|
||||
if not is_control: return
|
||||
|
||||
if eve.direction == Gdk.ScrollDirection.SMOOTH:
|
||||
has_deltas, dx, dy = eve.get_scroll_deltas()
|
||||
if not has_deltas: return False
|
||||
|
||||
if dy < 0:
|
||||
source_view.command.exec("zoom_in")
|
||||
elif dy > 0:
|
||||
source_view.command.exec("zoom_out")
|
||||
|
||||
return True
|
||||
|
||||
if eve.direction == Gdk.ScrollDirection.UP:
|
||||
source_view.command.exec("zoom_in")
|
||||
elif eve.direction == Gdk.ScrollDirection.DOWN:
|
||||
source_view.command.exec("zoom_out")
|
||||
|
||||
return True
|
||||
|
||||
def populate_popup(self, source_view, menu, emit):
|
||||
buffer = source_view.get_buffer()
|
||||
event = Event_Factory.create_event(
|
||||
|
||||
@@ -61,7 +61,6 @@ class SourceViewsMultiInsertState(SourceViewsBaseState):
|
||||
self.marker_manager.apply_to_marks(buffer, replace_word)
|
||||
return True
|
||||
|
||||
|
||||
def move_cursor(self, source_view, step, count, is_selection, emit):
|
||||
is_forward = count > 0
|
||||
buffer = source_view.get_buffer()
|
||||
@@ -78,6 +77,8 @@ class SourceViewsMultiInsertState(SourceViewsBaseState):
|
||||
|
||||
self._signal_cursor_moved(source_view, emit)
|
||||
|
||||
return False
|
||||
|
||||
def key_press_event(self, source_view, event, key_mapper):
|
||||
char = key_mapper.get_raw_keyname(event).upper()
|
||||
self.is_control = key_mapper.is_control(event)
|
||||
|
||||
@@ -106,7 +106,6 @@ class MarkSupportMixin:
|
||||
name = f"multi-insert-end-{hash}",
|
||||
left_gravity = False
|
||||
)
|
||||
# left_gravity = True
|
||||
|
||||
buffer.add_mark(start_mark, target_iter)
|
||||
buffer.add_mark(end_mark, target_iter)
|
||||
|
||||
Reference in New Issue
Block a user