Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions LaTeXTools.sublime-settings
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@
// You can also use toggle: C-l,t,a,e
"env_auto_trigger": false,

// Fill-helper autocompletion will close automatically an environment after \begin{. This trigger is only ran after you have selected an environment from the list
// This autoclose is only triggered when adding a new \begin{, not when modifying an existing one via the Window Command Palette
// This requires "env_auto_trigger" to be true.
"env_autoclose_trigger": false,

// Fill-helper autocompletion triggered for a wide range of references to external
// files. You can also use toggle: C-l,t,a,f
"fill_auto_trigger": true,
Expand All @@ -120,6 +125,9 @@
// You can also use the toggle C-l,t,a,b
"smart_bracket_auto_trigger": true,

// After Fill-helper autocompletion has finished his completion, moves the cursor after the closing bracket if there is one.
"smart_cursor_move_auto_trigger": false,

// ------------------------------------------------------------------
// Image Preview Settings
// ------------------------------------------------------------------
Expand Down
34 changes: 34 additions & 0 deletions latextools/latex_env_completions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from .utils import analysis
from .utils.settings import get_setting
from .utils.tex_directives import get_tex_root
from .utils.sublime_utils import move_cursor_relative, move_cursor_vertical

BEGIN_END_BEFORE_REGEX = re.compile(r"([^{}\[\]]*)\{(?:\][^{}\[\]]*\[)?(?:nigeb|dne)\\")
"""
Expand Down Expand Up @@ -63,6 +64,39 @@ def get_completions(self, view, prefix, line):

return (display, values)

def on_selection(self, view, insert_text, should_complete):
# Do nothing the fill helper was called to replace the content of a command
if not should_complete or not get_setting("env_autoclose_trigger", False):
return

# The \end{...} is added only if there is a single cursor and if the 4 characters before the cursor are "\end"
sel = view.sel()
take_selection = [True]*len(sel) # Indicates if we need the Region at index i will undergo autoclose of environment
indentation = [0] * len(sel)
for i in range(len(sel)):
cursor = sel[i].end()

# Determines the characters before the cursor
before_bracket = cursor - 1 - len(insert_text)
begin = view.substr(sublime.Region(before_bracket-4, before_bracket))

# Returns if we should not insert the closing environment
if begin == "\\end":
take_selection[i] = False

# First, move the cursor after the {}
move_cursor_relative(sel, 1, take_selection)

# Insert the \end{...}
text_insert = f"\n\\end{{{insert_text}}}"
view.run_command("insert", {"characters": text_insert})

# Place the cursor at the end of the line containing the \begin{...}
move_cursor_vertical(view, sel, -1, take_cursor=take_selection)

# Add a \n\t for correct indentation
view.run_command("insert", {"characters": "\n\t"})

def matches_line(self, line):
return bool(BEGIN_END_BEFORE_REGEX.match(line))

Expand Down
21 changes: 21 additions & 0 deletions latextools/latex_fill_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from .utils.decorators import async_completions
from .utils.logging import logger
from .utils.settings import get_setting
from .utils.sublime_utils import move_cursor_relative

__all__ = [
"LatexFillAllEventListener",
Expand Down Expand Up @@ -80,6 +81,24 @@ def get_completions(self, view, prefix, line):
"""
return None

def on_selection(self, view, insert_text, should_complete):
"""
Code executed after the user has selected a completion and after the completion has been inserted in the view

:param view:
The current `View` being edited

:param insert_text:
Text used for the completion

:param should_complete:
Indicates if the fill helper is replacing an existing element or completing a newly created one

"""
# If we add a new element, moves the cursor after the closing bracket
if should_complete and get_setting("smart_cursor_move_auto_trigger", False):
move_cursor_relative(view.sel(), 1)

def matches_line(self, line):
"""
Checks if this plugin matches the current line
Expand Down Expand Up @@ -1108,6 +1127,8 @@ def on_done(i, text=""):
"remove_regions": self.regions_to_tuples(remove_regions),
},
)

completion_type.on_selection(view, insert_text, should_complete=(insert_char != ''))

# track visible input quick panels to provide key binding context
VISIBLE_OVERLAYS.add(window.id())
Expand Down
64 changes: 64 additions & 0 deletions latextools/utils/sublime_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,67 @@ def get_project_file_name(view: sublime.View) -> str | None:
if window:
return window.project_file_name()
return None

def move_cursor_relative(sel, drift, take_cursor=None):
"""
Moves the cursor relatively from its current position

:param sel:
`Selection` containing all the `Region`s to update

:param drift:
Number of character the cursor must move

:param take_cursor:
Optional array of booleans indicating if the ith `Region` must be moved. Note that take_cursor must have the same length as sel!
"""
new_regions = []

for i in range(len(sel)):
region = sel[i]
pos = region.end()
if take_cursor is None or take_cursor[i]:
pos = pos + drift

new_regions.append(sublime.Region(pos))

sel.clear()
for r in new_regions:
sel.add(r)

def move_cursor_vertical(view, sel, drift, take_cursor=None):
"""
Moves the cursor to the beginning of the next line or to the end of the previous line

:param view:
Current view object

:param sel:
`Selection` containing all the `Region`s to update

:param drift:
+1 to go to the previous line, -1 to go to the next line

:param take_cursor:
Optional array of booleans indicating if the ith `Region` must be moved. Note that take_cursor must have the same length as sel!
"""
new_regions = []

for i in range(len(sel)):
region = sel[i]
pos = region.end()

print("Before: ", pos)
if take_cursor is None or take_cursor[i]:
# Get the current line
line = view.line(pos)
if drift > 0:
pos = line.end() + 1
else:
pos = line.begin() - 1

new_regions.append(sublime.Region(pos))

sel.clear()
for r in new_regions:
sel.add(r)