Home Download Buy Blog Forum Support

Split/iterate [regions]

Re: Split/iterate [regions]

Postby facelessuser on Sun Oct 07, 2012 1:38 pm

castles_made_of_sand wrote:>>> not prototyping things like array

Are you talking about JavaScript extending of prototypes?


Yeah, I meant Javascript. Post corrected.

castles_made_of_sand wrote:>>> if you are going to be communicating with other plugins, then you might have a problem

?

Edit: wrong quote, but this was referring to other people mucking with the same kind of monkey patches.
facelessuser
 
Posts: 1459
Joined: Tue Apr 05, 2011 7:38 pm

Re: Split/iterate [regions]

Postby facelessuser on Sun Oct 07, 2012 1:41 pm

castles_made_of_sand wrote:>>> As long as the API functions don't really check the types of what you send in, you could use something like that

Code: Select all
>>> rs = PyRegionSet(list(view.sel()))
>>> view.add_regions('derpa', rs, '')
>>> view.get_regions('derpa')
[(2131, 2131)]


Good to know.
facelessuser
 
Posts: 1459
Joined: Tue Apr 05, 2011 7:38 pm

Re: Split/iterate [regions]

Postby sublimator on Sun Oct 07, 2012 1:47 pm

For the record, I do wish things like __iter__/__hash__ were defined and indeed, boost::python is designed explicitly for the classes to be re opened. You can't patch normal C extension builtin objects.
It is better to remain silent and be thought a fool, than to speak out and remove all doubt
sublimator
 
Posts: 648
Joined: Thu Mar 20, 2008 5:41 am

Re: Split/iterate [regions]

Postby facelessuser on Sun Oct 07, 2012 1:54 pm

castles_made_of_sand wrote:For the record, I do wish things like __iter__/__hash__ were defined and indeed, boost::python is designed explicitly for the classes to be re opened. You can't patch normal C extension builtin objects.


Ahh. You are correct. I had not tested that. I have not used said monkey patch, and was only showing it as a concept, but it appears to be greatly flawed if communicating with the API. C is not so forgiving of class types as python is.
facelessuser
 
Posts: 1459
Joined: Tue Apr 05, 2011 7:38 pm

Re: Split/iterate [regions]

Postby agibsonsw on Sun Oct 07, 2012 1:57 pm

Thanks for the code @castles. I don't need this yet but shall bear it in mind 8-)

Code: Select all
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.
"I'm here to save your life. But if I'm going to do that, I'll need total uninanonynymity." Me Myself & Irene.
agibsonsw
 
Posts: 901
Joined: Fri Jan 27, 2012 9:11 pm

Re: Split/iterate [regions]

Postby facelessuser on Sun Oct 07, 2012 2:07 pm

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.
facelessuser
 
Posts: 1459
Joined: Tue Apr 05, 2011 7:38 pm

Re: Split/iterate [regions]

Postby agibsonsw on Sun Oct 07, 2012 2:15 pm

Well got it working - seems to be behaving 8-). 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 :D. It would be really nice if someone gave it a quick test run (please).

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


Code: Select all
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(r)
            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")

It occasionally drops the first letter of the edited text(?) and, as mentioned, I would like to collapse two adjacent regions. Regards, Andy.
Attachments
LastEditLine.zip
(993 Bytes) Downloaded 61 times
"I'm here to save your life. But if I'm going to do that, I'll need total uninanonynymity." Me Myself & Irene.
agibsonsw
 
Posts: 901
Joined: Fri Jan 27, 2012 9:11 pm

Re: Split/iterate [regions]

Postby agibsonsw on Sun Oct 07, 2012 3:04 pm

I will use

Code: Select all
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..
"I'm here to save your life. But if I'm going to do that, I'll need total uninanonynymity." Me Myself & Irene.
agibsonsw
 
Posts: 901
Joined: Fri Jan 27, 2012 9:11 pm

Re: Split/iterate [regions]

Postby agibsonsw on Sun Oct 07, 2012 4:33 pm

This version is working perfectly now!

Code: Select all
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(r).strip()
            if not len(curr_text):
                curr_text = self.view.substr(self.view.line(r)).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)

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 ;) .

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..
Attachments
AndyEdits.zip
(1.1 KiB) Downloaded 58 times
"I'm here to save your life. But if I'm going to do that, I'll need total uninanonynymity." Me Myself & Irene.
agibsonsw
 
Posts: 901
Joined: Fri Jan 27, 2012 9:11 pm

Re: Split/iterate [regions]

Postby agibsonsw on Sun Oct 07, 2012 4:58 pm

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

Code: Select all
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(r)
        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(r).strip()
            if not len(curr_text):
                curr_text = self.view.substr(self.view.line(r)).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)
"I'm here to save your life. But if I'm going to do that, I'll need total uninanonynymity." Me Myself & Irene.
agibsonsw
 
Posts: 901
Joined: Fri Jan 27, 2012 9:11 pm

PreviousNext

Return to Technical Support

Who is online

Users browsing this forum: pythoner, Yahoo [Bot] and 36 guests

cron