AttractText deletes the current line instead of doing nothing when the selection is on an empty first line of the buffer.
class AttractText(sublime_plugin.TextCommand):
def run(self, edit):
view = self.view
prev_line = view.line(view.text_point(view.rowcol(view.sel()[0].begin())[0] - 1, 0))
next_line = view.line(view.text_point(view.rowcol(view.sel()[-1].end())[0] + 1, 0))
if next_line.empty() or (slm_settings.get('squash_whitespace_only_lines') and view.substr(next_line).isspace()):
view.erase(edit, sublime.Region(next_line.begin(), next_line.end() + 1))
if prev_line.empty() or (slm_settings.get('squash_whitespace_only_lines') and view.substr(prev_line).isspace()):
first_line = view.rowcol(view.visible_region().begin())[0]
view.erase(edit, sublime.Region(prev_line.begin(), prev_line.end() + 1))
shift_view(view, -1)
When the selection is on row 0 (the buffer's first line), view.rowcol(...)[0] - 1 is -1, and view.text_point(-1, 0) clamps to 0 instead of erroring — so prev_line resolves to the same line the selection is already on, not "no line above" as intended. If that first line happens to be empty, prev_line.empty() is True, and the command erases Region(prev_line.begin(), prev_line.end() + 1) — i.e. it deletes the very line the cursor is sitting on, not a genuinely separate line above it.
Repro:
- Create a buffer starting with a blank line:
\nline1\nline2\n.
- Place the cursor on line 1 (the empty first line, row 0).
- Run "Attract Text".
- Expected: nothing happens (there's no line above the first line to pull down).
- Actual: the first line is erased, and the view shifts up by one line height — the buffer becomes
line1\nline2\n and the cursor's line is gone.
Suggested fix: guard the "previous line" branch so it's skipped when the selection is already on the first line, e.g.:
current_row = view.rowcol(view.sel()[0].begin())[0]
if current_row > 0:
prev_line = view.line(view.text_point(current_row - 1, 0))
if prev_line.empty() or ...:
...
AttractTextdeletes the current line instead of doing nothing when the selection is on an empty first line of the buffer.When the selection is on row 0 (the buffer's first line),
view.rowcol(...)[0] - 1is-1, andview.text_point(-1, 0)clamps to0instead of erroring — soprev_lineresolves to the same line the selection is already on, not "no line above" as intended. If that first line happens to be empty,prev_line.empty()isTrue, and the command erasesRegion(prev_line.begin(), prev_line.end() + 1)— i.e. it deletes the very line the cursor is sitting on, not a genuinely separate line above it.Repro:
\nline1\nline2\n.line1\nline2\nand the cursor's line is gone.Suggested fix: guard the "previous line" branch so it's skipped when the selection is already on the first line, e.g.: