Sublime Forum

Split/iterate [regions]

#15

Thanks for the code @castles. I don’t need this yet but shall bear it in mind :sunglasses:

edited = self.view.get_regions("edited_rgns") or ]

I just need two things now:
I want to select from “edited_rgns” based on its index number(s) - facelessuser’s code could do this but I’m not sure I need it just yet.

How would you converge my regions in “edited_rgns”. That is, if two regions are touching (or overlap) how can I convert them into one region please? Although ST seems to occasionally do this of its own accord if one region is contained within another.

0 Likes

#16

Don’t use mine if you intend to modify the Region class. Only use it as its own function that simply converts the regionset. Boost will not like you tampering with the base class.

0 Likes

#17

Well got it working - seems to be behaving :sunglasses:. I’ve re-written my LastEditLine (overnight…) code so that it maintains hidden regions that coincide with the edited content. I can now invoke a quick panel to list and jump to the edited lines :smiley:. It would be really nice if someone gave it a quick test run (please).

{ "keys": "ctrl+alt+j"], "command": "quick_edits" }, { "keys": "ctrl+alt+k"], "command": "prev_edit_line" }, { "keys": "ctrl+alt+l"], "command": "next_edit_line" }

[code]import sublime, sublime_plugin

class PrevEditLineCommand(sublime_plugin.TextCommand):
def run(self, edit):
vid = self.view.id()
sel = self.view.sel()[0]
currA = sel.begin()
currB = sel.end()
curr_line, _ = self.view.rowcol(currA)
edited = self.view.get_regions(“edited_rgns”) or ]
edited_last = self.view.get_regions(“edited_rgn”) or ]
if not edited and not edited_last:
return
edited.extend(edited_last)
self.view.add_regions(“edited_rgns”, edited, “edits”, sublime.HIDDEN)
self.view.erase_regions(“edited_rgn”)
edited = self.view.get_regions(“edited_rgns”) or ]

    for reg in [r for r in reversed(edited) if r.begin() < currA]:
        self.view.sel().clear()
        self.view.show(reg)
        self.view.sel().add(reg)
        break

class NextEditLineCommand(sublime_plugin.TextCommand):
def run(self, edit):
vid = self.view.id()
sel = self.view.sel()[0]
currA = sel.begin()
currB = sel.end()
curr_line, _ = self.view.rowcol(currA)
edited = self.view.get_regions(“edited_rgns”) or ]
edited_last = self.view.get_regions(“edited_rgn”) or ]
if not edited and not edited_last:
return
edited.extend(edited_last)
self.view.add_regions(“edited_rgns”, edited, “edits”, sublime.HIDDEN)
self.view.erase_regions(“edited_rgn”)
edited = self.view.get_regions(“edited_rgns”) or ]

    for reg in [r for r in edited if r.begin() > currA]:
        self.view.sel().clear()
        self.view.show(reg)
        self.view.sel().add(reg)
        break

class QuickEditsCommand(sublime_plugin.TextCommand):
def run(self, edit):
window = sublime.active_window()
view = window.active_view() if window != None else None
if view is None or view.id() != self.view.id():
sublime.status_message(‘Click into the view/tab first.’)
return
edited = self.view.get_regions(“edited_rgns”) or ]
edited_last = self.view.get_regions(“edited_rgn”) or ]
if not edited and not edited_last:
sublime.status_message(‘No edits to list.’)
return
edited.extend(edited_last)
self.view.add_regions(“edited_rgns”, edited, “edits”, sublime.HIDDEN)
self.view.erase_regions(“edited_rgn”)
edited = self.view.get_regions(“edited_rgns”) or ]
the_edits = ]
for i, r in enumerate(edited):
curr_line, _ = self.view.rowcol(r.begin())
curr_text = self.view.substr®
the_edits.append(“Line: %03d %s” % ( curr_line, curr_text ))
window.show_quick_panel(the_edits, self.on_chosen)

def on_chosen(self, index):
    if index == -1: return
    edited = self.view.get_regions("edited_rgns") or ]
    for reg in [r for i, r in enumerate(edited) if i == index]:
        self.view.sel().clear()
        self.view.show(reg)
        self.view.sel().add(reg)
        break

class CaptureEditing(sublime_plugin.EventListener):
def on_modified(self, view):
# create hidden regions that mirror the edited regions
vid = view.id()
sel = view.sel()[0]
currA = sel.begin()
currB = sel.end()
self.curr_line, _ = view.rowcol(currA)
if not hasattr(self, ‘prev_line’):
self.prev_line = self.curr_line
self.lastx = currA
self.lasty = currB
self.curr_edit = sublime.Region(self.lastx, self.lasty)
view.add_regions(“edited_rgn”,[self.curr_edit], “edits”, sublime.HIDDEN)
return
if self.curr_line == self.prev_line:
self.lastx = min(currA, self.lastx)
self.lasty = max(currB, self.lasty)
self.curr_edit = sublime.Region(self.lastx, self.lasty)
view.add_regions(“edited_rgn”,[self.curr_edit], “edits”, sublime.HIDDEN)
else:
self.prev_line = self.curr_line
self.lastx = currA
self.lasty = currB
edited = view.get_regions(“edited_rgns”) or ]
edited_last = view.get_regions(“edited_rgn”) or ]
if not edited and not edited_last:
return
edited.extend(edited_last)
view.add_regions(“edited_rgns”, edited, “edits”, sublime.HIDDEN)
view.erase_regions(“edited_rgn”)
[/code]
It occasionally drops the first letter of the edited text(?) and, as mentioned, I would like to collapse two adjacent regions. Regards, Andy.
LastEditLine.zip (993 Bytes)

0 Likes

#18

I will use

if not len(curr_text.strip()): curr_text = self.view.substr(self.view.line(r)) + " (line)"
so that, if the edit is just whitespace, it will instead display the full line in the quick panel.

It does seem to connect adjoining regions (sometimes…) but I’ll need to test this a bit more. But I still need to resolve it dropping the first edit-character…

0 Likes

#19

This version is working perfectly now!

[code]import sublime, sublime_plugin

def AdjustEdits(view):
edited = view.get_regions(“edited_rgns”) or ]
edited_last = view.get_regions(“edited_rgn”) or ]
if not edited and not edited_last:
return False
edited.extend(edited_last)
view.add_regions(“edited_rgns”, edited, “edits”, sublime.HIDDEN)
view.erase_regions(“edited_rgn”)
return view.get_regions(“edited_rgns”) or ]

class PrevEditLineCommand(sublime_plugin.TextCommand):
def run(self, edit):
vid = self.view.id()
currA = self.view.sel()[0].begin()
edited = AdjustEdits(self.view)
if not edited:
sublime.status_message(‘No edits to go to.’)
return
for reg in [r for r in reversed(edited) if r.begin() < currA]:
self.view.sel().clear()
self.view.show(reg)
self.view.sel().add(reg)
break
else:
sublime.status_message(‘No edits further up.’)

class NextEditLineCommand(sublime_plugin.TextCommand):
def run(self, edit):
vid = self.view.id()
currA = self.view.sel()[0].begin()
edited = AdjustEdits(self.view)
if not edited:
sublime.status_message(‘No edits to go to.’)
return
for reg in [r for r in edited if r.begin() > currA]:
self.view.sel().clear()
self.view.show(reg)
self.view.sel().add(reg)
break
else:
sublime.status_message(‘No edits further down.’)

class QuickEditsCommand(sublime_plugin.TextCommand):
def run(self, edit):
window = sublime.active_window()
view = window.active_view() if window != None else None
if view is None or view.id() != self.view.id():
sublime.status_message(‘Click into the view/tab first.’)
return
self.vid = self.view.id()
edited = AdjustEdits(self.view)
if not edited:
sublime.status_message(‘No edits to list.’)
return
the_edits = ]
for i, r in enumerate(edited):
curr_line, _ = self.view.rowcol(r.begin())
curr_text = self.view.substr®.strip()
if not len(curr_text):
curr_text = self.view.substr(self.view.line®).strip():40]
+ " (line)"
the_edits.append(“Line: %03d %s” % ( curr_line + 1, curr_text ))
window.show_quick_panel(the_edits, self.on_chosen)

def on_chosen(self, index):
    if index == -1: return
    window = sublime.active_window()
    view = window.active_view() if window != None else None
    if view is None or view.id() != self.vid:
        sublime.status_message('You are in a different view.')
        return
    edited = self.view.get_regions("edited_rgns") or ]
    for reg in [r for i, r in enumerate(edited) if i == index]:
        self.view.sel().clear()
        self.view.show(reg)
        self.view.sel().add(reg)
        break

class CaptureEditing(sublime_plugin.EventListener):
def on_modified(self, view):
# create hidden regions that mirror the edited regions
vid = view.id()
sel = view.sel()[0]
currA, currB = (sel.begin(), sel.end())
self.curr_line, _ = view.rowcol(currA)
if not hasattr(self, ‘prev_line’):
self.prev_line = self.curr_line
if currA > 0 and sel.empty():
currA -= 1
self.lastx, self.lasty = (currA, currB)
self.curr_edit = sublime.Region(self.lastx, self.lasty)
view.add_regions(“edited_rgn”,[self.curr_edit], “edits”, sublime.HIDDEN)
return
if self.curr_line == self.prev_line:
self.lastx = min(currA, self.lastx)
self.lasty = max(currB, self.lasty)
self.curr_edit = sublime.Region(self.lastx, self.lasty)
view.add_regions(“edited_rgn”,[self.curr_edit], “edits”, sublime.HIDDEN)
else:
self.prev_line = self.curr_line
if currA > 0 and sel.empty():
currA -= 1
self.lastx, self.lasty = (currA, currB)
_ = AdjustEdits(view)[/code]
I’m not really interested in jumping between views (as some others have done) nor in ordering them by edit-time, or storing the information between sessions. However, I retain an open mind so wont ignore requests :wink: .

The only other thing I’m considering at the moment is to, perhaps, toggle highlighting of edited text.

BTW There are already alternative versions of this available on PackageControl - but not as good as mine, he, he! Andy.

Added: I might try a combine consecutive edited lines though…
AndyEdits.zip (1.1 KB)

0 Likes

#20

Wow, that didn’t take long! Consecutive edited-lines will be treated as one edit:

[code]import sublime, sublime_plugin

def AdjustEdits(view):
edited = view.get_regions(“edited_rgns”) or ]
edited_last = view.get_regions(“edited_rgn”) or ]
if not edited and not edited_last:
return False
new_edits = ]
edited.extend(edited_last)
for i, r in enumerate(edited):
if i > 0 and r.begin() == prev_end:
new_edits.append(sublime.Region(prev_begin, r.end()))
else:
new_edits.append®
prev_begin, prev_end = (r.begin(), r.end())

view.add_regions("edited_rgns", new_edits, "edits", sublime.HIDDEN)
view.erase_regions("edited_rgn")
return view.get_regions("edited_rgns") or ]

class PrevEditLineCommand(sublime_plugin.TextCommand):
def run(self, edit):
vid = self.view.id()
currA = self.view.sel()[0].begin()
edited = AdjustEdits(self.view)
if not edited:
sublime.status_message(‘No edits to go to.’)
return
for reg in [r for r in reversed(edited) if r.begin() < currA]:
self.view.sel().clear()
self.view.show(reg)
self.view.sel().add(reg)
break
else:
sublime.status_message(‘No edits further up.’)

class NextEditLineCommand(sublime_plugin.TextCommand):
def run(self, edit):
vid = self.view.id()
currA = self.view.sel()[0].begin()
edited = AdjustEdits(self.view)
if not edited:
sublime.status_message(‘No edits to go to.’)
return
for reg in [r for r in edited if r.begin() > currA]:
self.view.sel().clear()
self.view.show(reg)
self.view.sel().add(reg)
break
else:
sublime.status_message(‘No edits further down.’)

class QuickEditsCommand(sublime_plugin.TextCommand):
def run(self, edit):
window = sublime.active_window()
view = window.active_view() if window != None else None
if view is None or view.id() != self.view.id():
sublime.status_message(‘Click into the view/tab first.’)
return
self.vid = self.view.id()
edited = AdjustEdits(self.view)
if not edited:
sublime.status_message(‘No edits to list.’)
return
the_edits = ]
for i, r in enumerate(edited):
curr_line, _ = self.view.rowcol(r.begin())
curr_text = self.view.substr®.strip()
if not len(curr_text):
curr_text = self.view.substr(self.view.line®).strip():40]
+ " (line)"
the_edits.append(“Line: %03d %s” % ( curr_line + 1, curr_text ))
window.show_quick_panel(the_edits, self.on_chosen)

def on_chosen(self, index):
    if index == -1: return
    window = sublime.active_window()
    view = window.active_view() if window != None else None
    if view is None or view.id() != self.vid:
        sublime.status_message('You are in a different view.')
        return
    edited = self.view.get_regions("edited_rgns") or ]
    for reg in [r for i, r in enumerate(edited) if i == index]:
        self.view.sel().clear()
        self.view.show(reg)
        self.view.sel().add(reg)
        break

class CaptureEditing(sublime_plugin.EventListener):
def on_modified(self, view):
# create hidden regions that mirror the edited regions
vid = view.id()
sel = view.sel()[0]
currA, currB = (sel.begin(), sel.end())
self.curr_line, _ = view.rowcol(currA)
if not hasattr(self, ‘prev_line’):
self.prev_line = self.curr_line
if currA > 0 and sel.empty():
currA -= 1
self.lastx, self.lasty = (currA, currB)
self.curr_edit = sublime.Region(self.lastx, self.lasty)
view.add_regions(“edited_rgn”,[self.curr_edit], “edits”, sublime.HIDDEN)
return
if self.curr_line == self.prev_line:
self.lastx = min(currA, self.lastx)
self.lasty = max(currB, self.lasty)
self.curr_edit = sublime.Region(self.lastx, self.lasty)
view.add_regions(“edited_rgn”,[self.curr_edit], “edits”, sublime.HIDDEN)
else:
self.prev_line = self.curr_line
if currA > 0 and sel.empty():
currA -= 1
self.lastx, self.lasty = (currA, currB)
_ = AdjustEdits(view)[/code]

0 Likes

#21

Finished! I can toggle the display of the edited regions (Ctrl+Alt+H) and they are persistent. That is, if you close the application then they will persist, but not if you close the file/view (this is how persistence behaves by default in ST).

{ "keys": "ctrl+alt+h"], "command": "toggle_edits" }, { "keys": "ctrl+alt+j"], "command": "quick_edits" }, { "keys": "ctrl+alt+k"], "command": "prev_edit_line" }, { "keys": "ctrl+alt+l"], "command": "next_edit_line" }

[code]import sublime, sublime_plugin

def AdjustEdits(view):
edited = view.get_regions(“edited_rgns”) or ]
edited_last = view.get_regions(“edited_rgn”) or ]
if not edited and not edited_last:
return False
new_edits = ]
edited.extend(edited_last)
for i, r in enumerate(edited):
if i > 0 and r.begin() == prev_end:
new_edits.append(sublime.Region(prev_begin, r.end()))
else:
new_edits.append®
prev_begin, prev_end = (r.begin(), r.end())

view.add_regions("edited_rgns", new_edits, "edits", \
    sublime.HIDDEN | sublime.PERSISTENT)
view.erase_regions("edited_rgn")
return view.get_regions("edited_rgns") or ]

class ToggleEditsCommand(sublime_plugin.TextCommand):
def run(self, edit):
edited = AdjustEdits(self.view)
if not edited:
sublime.status_message(‘No edits to show or hide.’)
return
toggled = self.view.get_regions(“toggled_edits”) or ]
if toggled:
self.view.erase_regions(“toggled_edits”)
else:
self.view.add_regions(“toggled_edits”, edited, “keyword”,
sublime.DRAW_OUTLINED)

class PrevEditLineCommand(sublime_plugin.TextCommand):
def run(self, edit):
vid = self.view.id()
currA = self.view.sel()[0].begin()
edited = AdjustEdits(self.view)
if not edited:
sublime.status_message(‘No edits to go to.’)
return
for reg in [r for r in reversed(edited) if r.begin() < currA]:
self.view.sel().clear()
self.view.show(reg)
self.view.sel().add(reg)
break
else:
sublime.status_message(‘No edits further up.’)

class NextEditLineCommand(sublime_plugin.TextCommand):
def run(self, edit):
vid = self.view.id()
currA = self.view.sel()[0].begin()
edited = AdjustEdits(self.view)
if not edited:
sublime.status_message(‘No edits to go to.’)
return
for reg in [r for r in edited if r.begin() > currA]:
self.view.sel().clear()
self.view.show(reg)
self.view.sel().add(reg)
break
else:
sublime.status_message(‘No edits further down.’)

class QuickEditsCommand(sublime_plugin.TextCommand):
def run(self, edit):
window = sublime.active_window()
view = window.active_view() if window != None else None
if view is None or view.id() != self.view.id():
sublime.status_message(‘Click into the view/tab first.’)
return
self.vid = self.view.id()
edited = AdjustEdits(self.view)
if not edited:
sublime.status_message(‘No edits to list.’)
return
the_edits = ]
for i, r in enumerate(edited):
curr_line, _ = self.view.rowcol(r.begin())
curr_text = self.view.substr®.strip():40]
if not len(curr_text):
curr_text = self.view.substr(self.view.line®).strip():40]
+ " (line)"
the_edits.append(“Line: %03d %s” % ( curr_line + 1, curr_text ))
window.show_quick_panel(the_edits, self.on_chosen)

def on_chosen(self, index):
    if index == -1: return
    window = sublime.active_window()
    view = window.active_view() if window != None else None
    if view is None or view.id() != self.vid:
        sublime.status_message('You are in a different view.')
        return
    edited = self.view.get_regions("edited_rgns") or ]
    for reg in [r for i, r in enumerate(edited) if i == index]:
        self.view.sel().clear()
        self.view.show(reg)
        self.view.sel().add(reg)
        break

class CaptureEditing(sublime_plugin.EventListener):
def on_modified(self, view):
# create hidden regions that mirror the edited regions
vid = view.id()
sel = view.sel()[0]
currA, currB = (sel.begin(), sel.end())
self.curr_line, _ = view.rowcol(currA)
if not hasattr(self, ‘prev_line’):
self.prev_line = self.curr_line
if currA > 0 and sel.empty():
currA -= 1
self.lastx, self.lasty = (currA, currB)
self.curr_edit = sublime.Region(self.lastx, self.lasty)
view.add_regions(“edited_rgn”,[self.curr_edit], “edits”,
sublime.HIDDEN | sublime.PERSISTENT)
return
if self.curr_line == self.prev_line:
self.lastx = min(currA, self.lastx)
self.lasty = max(currB, self.lasty)
self.curr_edit = sublime.Region(self.lastx, self.lasty)
view.add_regions(“edited_rgn”,[self.curr_edit], “edits”,
sublime.HIDDEN | sublime.PERSISTENT)
else:
self.prev_line = self.curr_line
if currA > 0 and sel.empty():
currA -= 1
self.lastx, self.lasty = (currA, currB)
_ = AdjustEdits(view)[/code]
Not bad for a few hours work - I might actually use this :laughing:
AndyEdits.zip (1.28 KB)

0 Likes

#22

Talking of JavaScript prototypes…

Date.prototype.format = function (sFormat, twelve) { // Returns: A string version of the date. // Usage: date_instance.format("d mmm yy hh:nn:ss ap") or // date_instance.format("dddd dd mmmm hh:nn", true) // Defaults to YYYY/MM/DD. // twelve == true for a 12hr clock, or just AP or ap within // sFormat (for AM/PM or am/pm). // Use z or zzz for milliseconds and xx for suffixes (st, nd, etc.). var MonthNames = "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; var DayNames = "Sunday", "Monday", "Tueday", "Wednesday", "Thursday", "Friday", "Saturday" ]; var dDate = this || new Date(), D = dDate.getDate(), DDDD = DayNames[dDate.getDay()], DDD = DDDD.substr(0,3), M = dDate.getMonth()+1, MMMM = MonthNames[dDate.getMonth()], MMM = MMMM.substr(0,3), YYYY = dDate.getFullYear(), YY = ('' + YYYY).substr(2, 2), H = dDate.getHours(), N = dDate.getMinutes(), S = dDate.getSeconds(), Z = dDate.getMilliseconds(), ap = (H > 11) ? "pm" : "am", // pad with leading zeros, if required DD = ( D < 10 ? "0" : "" ) + D, MM = ( M < 10 ? "0" : "" ) + M, NN = ( N < 10 ? "0" : "" ) + N, SS = ( S < 10 ? "0" : "" ) + S, ZZZ = ( Z < 10 ? "00" : (Z < 100 ? "0" : "") ) + Z, XX; var AP = (sFormat && (sFormat.toUpperCase().indexOf('AP')+1)) ? ((sFormat.indexOf('ap')+1) ? ap : ap.toUpperCase()) : ''; if (twelve || AP) { H = (H < 12) ? (H || 12) : ((H - 12) || 12); } var HH = ( H < 10 ? "0" : "" ) + H; XX = (D == 1 || D == 21 || D == 31) ? "st" : ((D == 2 || D == 22) ? "nd" : ((D == 3 || D == 23) ? "rd" : "th")); sFormat = ( sFormat ) ? sFormat.toUpperCase() : 'YYYY/MM/DD'; var sParsed = sFormat.replace(/D{1,4}|M{1,4}|Y{2,4}|H{1,2}|N{1,2}|S{1,2}|Z{1,3}|XX|AP/g, function (m) { try { return eval(m); } catch (e) { return ''; } }); return sParsed; };

I appreciate the arguments about JS prototypes, but this is one exception I’m happy to use. I suppose it could be named **andyFormat ** :sunglasses:
[There are other versions than mine, but mine distinguishes between [b]AM and **am **and enables **suffixes **1st ,2nd etc…]

0 Likes

#23

Attached screenshot.


0 Likes

#24

Second/last screenshot.


0 Likes

#25

Sorry, but I should offer the following version which prevents anything happening if you are not in a View; that is, if you are in the Find dialog, or anywhere else.

[code]import sublime, sublime_plugin

def adjustEdits(view):
edited = view.get_regions(“edited_rgns”) or ]
edited_last = view.get_regions(“edited_rgn”) or ]
if not edited and not edited_last:
return False
new_edits = ]
edited.extend(edited_last)
for i, r in enumerate(edited):
if i > 0 and r.begin() == prev_end:
new_edits.append(sublime.Region(prev_begin, r.end()))
else:
new_edits.append®
prev_begin, prev_end = (r.begin(), r.end())

view.add_regions("edited_rgns", new_edits, "keyword", \
    sublime.HIDDEN | sublime.PERSISTENT)
view.erase_regions("edited_rgn")
return view.get_regions("edited_rgns") or ]

def showRegion(view, reg):
view.sel().clear()
view.show(reg)
view.sel().add(reg)

class ToggleEditsCommand(sublime_plugin.TextCommand):
def run(self, edit):
window = sublime.active_window()
view = window.active_view() if window != None else None
if view is None or view.id() != self.view.id():
sublime.status_message(‘Click into the view/tab first.’)
return
edited = adjustEdits(self.view)
if not edited:
sublime.status_message(‘No edits to show or hide.’)
return
toggled = self.view.get_regions(“toggled_edits”) or ]
if toggled:
self.view.erase_regions(“toggled_edits”)
else:
self.view.add_regions(“toggled_edits”, edited,
“keyword”, sublime.DRAW_OUTLINED)

class PrevEditLineCommand(sublime_plugin.TextCommand):
def run(self, edit):
window = sublime.active_window()
view = window.active_view() if window != None else None
if view is None or view.id() != self.view.id():
sublime.status_message(‘Click into the view/tab first.’)
return
currA = self.view.sel()[0].begin()
edited = adjustEdits(self.view)
if not edited:
sublime.status_message(‘No edits to go to.’)
return
for reg in [r for r in reversed(edited) if r.begin() < currA]:
showRegion(self.view, reg)
break
else:
sublime.status_message(‘No edits further up.’)

class NextEditLineCommand(sublime_plugin.TextCommand):
def run(self, edit):
window = sublime.active_window()
view = window.active_view() if window != None else None
if view is None or view.id() != self.view.id():
sublime.status_message(‘Click into the view/tab first.’)
return
currA = self.view.sel()[0].begin()
edited = adjustEdits(self.view)
if not edited:
sublime.status_message(‘No edits to go to.’)
return
for reg in [r for r in edited if r.begin() > currA]:
showRegion(self.view, reg)
break
else:
sublime.status_message(‘No edits further down.’)

class QuickEditsCommand(sublime_plugin.TextCommand):
def run(self, edit):
window = sublime.active_window()
view = window.active_view() if window != None else None
if view is None or view.id() != self.view.id():
sublime.status_message(‘Click into the view/tab first.’)
return
self.vid = self.view.id()
edited = adjustEdits(self.view)
if not edited:
sublime.status_message(‘No edits to list.’)
return
the_edits = ]
for i, r in enumerate(edited):
curr_line, _ = self.view.rowcol(r.begin())
curr_text = self.view.substr®.strip():40]
if not len(curr_text):
curr_text = self.view.substr(self.view.line®).strip():40]
+ " (line)"
the_edits.append(“Line: %03d %s” % ( curr_line + 1, curr_text ))
window.show_quick_panel(the_edits, self.on_chosen)

def on_chosen(self, index):
    if index == -1: return
    window = sublime.active_window()
    view = window.active_view() if window != None else None
    if view is None or view.id() != self.vid:
        sublime.status_message('You are in a different view.')
        return
    edited = self.view.get_regions("edited_rgns") or ]
    for reg in [r for i, r in enumerate(edited) if i == index]:
        showRegion(self.view, reg)
        break

class CaptureEditing(sublime_plugin.EventListener):
def on_modified(self, view):
# create hidden regions that mirror the edited regions
window = sublime.active_window()
curr_view = window.active_view() if window != None else None
if curr_view is None or curr_view.id() != view.id():
return
sel = view.sel()[0]
currA, currB = (sel.begin(), sel.end())
self.curr_line, _ = view.rowcol(currA)
if not hasattr(self, ‘prev_line’):
self.prev_line = self.curr_line
if currA > 0 and sel.empty():
currA -= 1
self.lastx, self.lasty = (currA, currB)
self.curr_edit = sublime.Region(self.lastx, self.lasty)
view.add_regions(“edited_rgn”,[self.curr_edit],
“keyword”, sublime.HIDDEN | sublime.PERSISTENT)
return
if self.curr_line == self.prev_line:
self.lastx = min(currA, self.lastx)
self.lasty = max(currB, self.lasty)
self.curr_edit = sublime.Region(self.lastx, self.lasty)
view.add_regions(“edited_rgn”,[self.curr_edit],
“keyword”, sublime.HIDDEN | sublime.PERSISTENT)
else:
self.prev_line = self.curr_line
if currA > 0 and sel.empty():
currA -= 1
self.lastx, self.lasty = (currA, currB)
_ = adjustEdits(view)[/code]

0 Likes

#26

My GitHub includes an icon :smile:

0 Likes

#27

Different icon - it’s a pencil :smiley: .

I shall stop now! But, of course, feedback is encouraged. Andy.


0 Likes

#28

@SimFox3
I’ve replied to your email but my responses are just sitting in my Outbox?!

You enquired about my **LastEditLine **command and I did copy this file initially to work on - but I got side-tracked and this revision doesn’t have the same feature-set. That is, it’s completely different :smiley: .

LastEditLine cycles through the last edit positions similar to the behaviour of Word (when pressing Shift F5). This was my intention, but I might revisit it once I’ve completed my AndyEdits :wink:

LastEditLine.zip (1.12 KB)*

0 Likes

#29

Someone has raised the following two issues:

[quote]
Hi, nice plugin, thanks for sharing.

I found 2 issues with it:

  1. When you change line, you need to make 2 change to trigger the edit icon on this line.
  2. When you trigger undo, the wrong edit icon is removed. To reproduce, modify 3 consecutive lines to show the edit icon on each, trigger undo -> the second to last icon is removed, not the last one. The subsequent undo work fine.

Number 2 is probably a ST2 bug, I’ve found regions in ST2 sometimes unreliable, especially with undo.[/quote]

I shall investigate these. If someone has experience with the Undo actions I will appreciate advice. I suspect it cannot be worked around; at least, not without substantial coding?

Actually, this sounds like the same issue, so if I fix the first one…

0 Likes

#30

I’ve fixed the first issue at my GitHub. I won’t post the code here, as it is now part of a package (including the icon) unless someone requests me to. This will also make the Undo behave slightly better, but I think the previously mentioned issue persists to some extent. I doubt that this can be fully overcome.

There is now an option to remove the edit history for a region (via a quick panel). This could be useful if you are performing a lot of edits on the same file and don’t wish to lose all the edit history by closing the file.

This new remove option enables you to use this package as a kind of workflow. Start different areas with a comment, so that this comment will appear as a title in the quick-panel list of edits. The continuous lines following the comment will be treated as a single edit-item. When completed, using Ctrl+Alt+D (or other shortcut) to *complete *the task. Added: Hint - you can also cut and paste the same line and it will be added as a new edit-item :sunglasses:


0 Likes

#31

I can confirm it’s fixed.

For the undo issue, I suppose only jps can give an answer…

0 Likes

#32

Undo seems to behave a little better now, as a result of the other fix. I think cutting and pasting the same content will be one way to correct edited regions, or even over-writing an area with a space or character, and then using Undo.

It just occurred to me that it *might *be useful to have another shortcut to specifically add the currently highlighted text as an edit-region. I might play with this. However, cutting and pasting achieves the same (or similar) result.

0 Likes

#33

Didn’t change anything for my test case but maybe it’s better for other test case.
Strangely, soft undo works without any issue for me.

So it looks more and more like a ST2 bug.
As jps not very active in this forum since a few weeks, anyone has it’s phone number :wink:

0 Likes

#34

I believe Undo (and other features - Duplicate, Cut, Paste) can be problematic with any plug-in. But for this simple plug-in it shouldn’t be a major concern, and most of these features seem to behave well. I find if I highlight an area, press Space and then Undo (Ctrl-Z) the whole area becomes a single edit-region. This process also removes any smaller edit regions within this larger area. In view of this, I don’t think it’s necessary for me to create a shortcut to do this (as mentioned in my previous post).

If anyone can think of something useful that might be added to this, please let me know - I might consider it :wink: . Otherwise, I think it’s complete - and I’m very pleased with it :smiley: :sunglasses:

0 Likes