116 lines
3.3 KiB
Python
116 lines
3.3 KiB
Python
from talon import Context, Module, actions
|
|
|
|
ctx = Context()
|
|
mod = Module()
|
|
|
|
|
|
@ctx.action_class("edit")
|
|
class EditActions:
|
|
def paragraph_start():
|
|
if extend_paragraph_start_with_success():
|
|
actions.edit.left()
|
|
|
|
def paragraph_end():
|
|
if extend_paragraph_end_with_success():
|
|
actions.edit.right()
|
|
|
|
def select_paragraph():
|
|
if is_line_empty():
|
|
return
|
|
# Search for start of paragraph
|
|
actions.edit.extend_paragraph_start()
|
|
actions.edit.left()
|
|
# Extend to end of paragraph
|
|
actions.edit.extend_paragraph_end()
|
|
|
|
def extend_paragraph_start():
|
|
# The reason for the wrapper function is a difference in function signature.
|
|
# The Talon action has no return value and the below function returns a boolean with success state.
|
|
extend_paragraph_start_with_success()
|
|
|
|
def extend_paragraph_end():
|
|
extend_paragraph_end_with_success()
|
|
|
|
def delete_paragraph():
|
|
actions.edit.select_paragraph()
|
|
# Remove selection
|
|
actions.edit.delete()
|
|
# Remove the empty line containing the cursor
|
|
actions.edit.delete()
|
|
# Remove leading or trailing empty line
|
|
actions.edit.delete_line()
|
|
|
|
|
|
@mod.action_class
|
|
class Actions:
|
|
def cut_paragraph():
|
|
"""Cut paragraph under the cursor"""
|
|
actions.edit.select_paragraph()
|
|
actions.edit.cut()
|
|
|
|
def copy_paragraph():
|
|
"""Copy paragraph under the cursor"""
|
|
actions.edit.select_paragraph()
|
|
actions.edit.copy()
|
|
|
|
def paste_paragraph():
|
|
"""Paste to paragraph under the cursor"""
|
|
actions.edit.select_paragraph()
|
|
actions.edit.paste()
|
|
|
|
|
|
def is_line_empty() -> bool:
|
|
"""Check if the current line is empty. Return True if empty."""
|
|
actions.edit.extend_line_start()
|
|
text = actions.edit.selected_text().strip()
|
|
if text:
|
|
actions.edit.right()
|
|
return False
|
|
actions.edit.extend_line_end()
|
|
text = actions.edit.selected_text().strip()
|
|
if text:
|
|
actions.edit.left()
|
|
return False
|
|
return True
|
|
|
|
|
|
def extend_paragraph_start_with_success() -> bool:
|
|
"""Extend selection to the start of the paragraph. Return True if successful."""
|
|
actions.edit.extend_line_start()
|
|
text = actions.edit.selected_text()
|
|
length = len(text)
|
|
while True:
|
|
actions.edit.extend_up()
|
|
actions.edit.extend_line_start()
|
|
text = actions.edit.selected_text()
|
|
new_length = len(text)
|
|
if new_length == length:
|
|
break
|
|
line = text[: new_length - length].strip()
|
|
if not line:
|
|
actions.edit.extend_down()
|
|
break
|
|
length = new_length
|
|
return text.strip() != ""
|
|
|
|
|
|
def extend_paragraph_end_with_success() -> bool:
|
|
"""Extend selection to the end of the paragraph. Return True if successful."""
|
|
actions.edit.extend_line_end()
|
|
text = actions.edit.selected_text()
|
|
length = len(text)
|
|
while True:
|
|
actions.edit.extend_down()
|
|
actions.edit.extend_line_end()
|
|
text = actions.edit.selected_text()
|
|
new_length = len(text)
|
|
if new_length == length:
|
|
break
|
|
line = text[length:].strip()
|
|
if not line:
|
|
actions.edit.extend_line_start()
|
|
actions.edit.extend_left()
|
|
break
|
|
length = new_length
|
|
return text.strip() != ""
|