@nk9 already done
I used that link years ago, and over the years made some modifications too it seems (I forgot I did).
I wonder if we should make this a plugin so everyone can benefit and find it on packagecontrol.io .
Ideally bizoo does so, but I doubt bizoo is still around. And bizoo will need a mention in the credits.
I have no idea how to go create and publish a plugin out of this though.
I see my previous post had some key commands that are not supported by the original plugin code, I’ll post my version of scroll_lines_fixed.py below that does support them:
import sublime
import sublime_plugin
# source original idea:
# https://stackoverflow.com/questions/17215334/sublime-text-2-how-to-page-up-down-without-moving-the-cursor
# https://forum.sublimetext.com/t/st2-how-to-page-up-down-without-moving-the-cursor/10434/4
# The idea is to only scroll the viewport and leave the cursor in place.
class ScrollLinesFixedCommand(sublime_plugin.TextCommand):
def run(self, edit, amount=1.0, to="", by="lines"):
if to == "cursor":
# scroll so cursor is at center of viewport, this command already exists:
self.view.run_command("show_at_center")
elif to == "top":
# scroll so first line of file is the top line in viewport:
curx, cury = self.view.viewport_position()
self.view.set_viewport_position((curx, 0))
elif to == "bottom":
# scroll so last line of file is the bottom line in viewport:
# - scroll to end.
# - scroll up a page so the entire last page is visible.
# - optional(?): scroll down 1 line so you see one empty line so that it is clear you are at the end?
# Could also be annoying waste of screen estate. Should be non-default, or optional. Or just dont.
curx, cury = self.view.viewport_position()
maxx, maxy = self.view.layout_extent()
pagewidth, pageheight = self.view.viewport_extent()
# optional 1 extra line:
# newy = maxy - pageheight + self.view.line_height()
newy = maxy - pageheight
self.view.set_viewport_position((curx, newy))
elif to == "linebegin":
curx, cury = self.view.viewport_position()
self.view.set_viewport_position((0, cury))
elif to == "lineend":
curx, cury = self.view.viewport_position()
curwidth, curheight = self.view.viewport_extent()
maxx, maxy = self.view.layout_extent()
self.view.set_viewport_position((maxx - curwidth, cury))
elif to == "left" or to == "right":
curx, cury = self.view.viewport_position()
curwidth, curheight = self.view.viewport_extent()
maxx, maxy = self.view.layout_extent()
if by == "page":
delta = curwidth * amount
else:
# TODO: make charwidth not hardcoded. 9.3 seems to work for me, with current (monospace) font.
charwidth = 9.3
delta = charwidth * amount
if to == "left":
delta *= -1
newx = curx + delta
# Works without min/max below, but if you go left or right too much
# and then go back you notice it takes a few extra moves to start scrolling again.
# It seems to keep scrolling even though it visually sticks within min max.
# hard to explain, but if you comment 2 lines below out you can see what I mean.
newx = max(newx, 0)
newx = min(newx, maxx - curwidth)
self.view.set_viewport_position((newx, cury))
# below: as builtin scroll_lines command, but without moving the cursor when it goes out of the visible area.
elif by != "lines" or (len(self.view.sel()) == 1 and self.view.sel()[0].empty()):
maxy = self.view.layout_extent()[1] - self.view.line_height()
curx, cury = self.view.viewport_position()
if by == "pages":
delta = self.view.viewport_extent()[1]
else:
delta = self.view.line_height()
nexty = cury - delta * amount
nexty = min(max(nexty, 0), maxy)
self.view.set_viewport_position((curx, nexty))
else:
self.view.run_command("scroll_lines", {"amount": amount})
The interface is a bit confusing with the mix of “amount” “to” and “by” maybe not always making sense. Probably need to think about that a bit more before making it public.
(I had no experience in python or sublime and just hacked at the original, so it’s not really up to proper coding or api standards)