Sublime Forum

BracketHighlighter

#59

@facelessuser,

Hey, thanks for BracketHighlighter. I didn’t know I needed it until I used it. Very helpful indeed.

Just one thing, though. Is it possible to not select the bracket/quote if the cursor is outside of it? For example, if I have the string:

“This is a string”

The quotes get highlighted when the cursor is outside of them. I’d like to highlight them only if the cursor is on the inside. I looked through the settings but didn’t see anything that seemed like it was related. I am not unwilling (there I go using a double negative!) to dig into the code and try to figure it out, but I know that these sorts of things can be quite complicated, especially if heavily dependent on regular expressions. I’m hoping you can very quickly say yea or nay and not have to spend much time at all digging into it.

Thanks again.

EDIT: Actually, I should be a bit more specific regarding what I’d like to see when the cursor is outside. If the bracket/quotes are nested, the surrounding bracket/quotes should be highlighted when the cursor is outside the quotes in question. For instance:

function say_hi()
{
    alert('Hi there');
}

In this example, I would expect the single quotes to be highlighted whenever the cursor is between them, but as soon as the cursor is outside of the single quotes (even immediately adjacent, but still outside), the parens of alert should be highlighted. As soon as the cursor is outside of the parens, the curly braces should highlight. As it is right now, you have to be at least one character away from a bracket/quote before it will not be highlighted and the surrounding bracket/quote highlighted.

I hope that makes sense. It is sometimes difficult to express in words something that is inherently visual.

0 Likes

#60

Current highlighting favors what ever is to the left of it. ST2s built in bracket underlining is very similar, but actually less consistant which makes brackets not get underlined in certain scenarios.

I chose a very consistant and predictable way to highlight. I think this better illustrates what I am doing:

With that said, I can add the logic in, but you may have to wait a little. I have been doing quite a bit of plugin coding recently and I think I need a little break :smile:.

The code is not done with regex…I think regex is the wrong tool for the job here (not to say it possibly can’t be done with regex). I understand thought that not being done with regex doesn’t always make the code easier to follow. If you really want to tinker with it and get this functionality before I get to it, you would probably look in adjacent_adjust, string_adjacent_adjust, and the very beginning of I think match_quotes. The first I believe handles brackets intial highlighting, the second handles brackets inside strings initial highlighting, and the third handles quote initial highlighting in the beginning.

If you get it working and would like to do a pull request the main things that I require is that it is optional, and you don’t break existing logic or functionality (the old method needs to work the same; it took me a little to iron logic out), and brakcets must be highlighted in some scenario no matter which direction the cursor comes from (cursor moving from left and cursor moving form right, the brackets need to fall into a scenario where they will always get highlighted.

That is it. If it is something you don’t want to mess with, I will try and get to it sometime soon, just create an issue in github so I don’t forget.

0 Likes

#61

[quote=“bizoo”]

Someone thanks you :wink:[/quote]

No problem :smile:. After you mentioned your issue, it made perfect sense to me, and it really was an easy setting to add.

0 Likes

#62

At the end, yes. When you’re at the beginning, it favors what’s on the right. Either way, you have to be one character away from a nested bracket in order for the surrounding pair to be highlighted.

[quote]ST2s built in bracket underlining is very similar, but actually less consistant which makes brackets not get underlined in certain scenarios.

I chose a very consistant and predictable way to highlight. [/quote]

Oh, I definitely like consistent and predictable! Ask my wife. Hah hah. Not saying your way is wrong, just that I’d prefer something slightly different. I applaud you for wanting a consistent user experience!

[quote]I think this better illustrates what I am doing:
[attachment=0]Screen Shot 2012-03-16 at 7.55.21 AM.png[/attachment]

With that said, I can add the logic in, but you may have to wait a little. I have been doing quite a bit of plugin coding recently and I think I need a little break :smile:.[/quote]

Totally understand!

Thanks for the pointers. That will save a bit of head scratching.

[quote]
If you get it working and would like to do a pull request the main things that I require is that it is optional, and you don’t break existing logic or functionality (the old method needs to work the same; it took me a little to iron logic out), and brakcets must be highlighted in some scenario no matter which direction the cursor comes from (cursor moving from left and cursor moving form right, the brackets need to fall into a scenario where they will always get highlighted.

That is it. If it is something you don’t want to mess with, I will try and get to it sometime soon, just create an issue in github so I don’t forget.[/quote]

Thanks for the detailed response. I might tinker with it this weekend and see what happens. If I get it working the way I want, I’ll submit a pull request. Otherwise an issue :smile:

0 Likes

#63

Yes it is not exclusive to the left; it will take whatever is adjacent. But if given the choice it favors the left.

It probably won’t be too bad. You could probably just wrap the adjacent call with a conditional block picking one of two adjacent adjust functions (yours and mine). I imagine you would just need a check to see if you are inside adjacent for the adjacent option, and possibly not offset the cursor like it is doing now…I am probably over simplifying, but yeah, it has got to simpler than what is being done now; same goes for brackets inside quotes. The quote adjacent might be a little uglier, it is a little ugly now, quotes were kind of a special case because the logic for them is a bit different.

Anyways good luck. If you have more questions, feel free to ask. I might be feeling lazy, but not so lazy I can’t consult to help someone do my dirty work :smile:.

0 Likes

#64

You shouldn’t have to touch match_quotes.

Maybe something like this would work:

def adjacent_adjust_inside(self, scout): # Offset cursor offset = 0 allow_quote_match = True # If quotes enbaled, kick out of adjacent check if in middle of string if ( self.view.score_selector(scout, 'string') > 0 and self.view.score_selector(scout - 1, 'string') > 0 and self.quote_enable ): return (offset, allow_quote_match) allow_quote_match = False char1 = self.view.substr(scout - 1) char2 = self.view.substr(scout) for bracket in self.targets: if char2 == self.brackets[bracket]'close']: offset = -1 self.adj_bracket = True break if char2 == self.brackets[bracket]'open'] and offset != -1: offset = -1 if char1 == self.brackets[bracket]'open']: if offset != -1: offset = -1 self.adj_bracket = True break return (offset, allow_quote_match)

And this for brackets inside strings:

def string_adjacent_adjust_inside(self, scout): # Offset cursor offset = 0 char1 = self.view.substr(scout - 1) char1_escaped = self.string_escaped(scout - 1) char2 = self.view.substr(scout) char2_escaped = self.string_escaped(scout) for bracket in self.targets: if char2 == self.brackets[bracket]'close'] and not char2_escaped: offset = -1 self.adj_bracket = True break if char2 == self.brackets[bracket]'open'] and not char2_escaped and offset != -1: offset = -1 if char1 == self.brackets[bracket]'open'] and not char1_escaped: if offset != -1: offset = -1 self.adj_bracket = True break return offset

You would need to add in the setting and the logic to use the proper function and just test it pretty good.

I used this in javascript to test basic functionality:

{('{()]}')]}

This should make it easier for you. This code might be what you need without alteration; I am not sure because I didn’t bother to test it out too good.

0 Likes

#65

Ahh crap. Looks like I sucked myself back in. :smile:

The more I thought about it the easier it seemed like it would be…so I went ahead and did it.

Version 1.6

  • Add setting to match only when cursor is between brackets

It is isolated with the setting, so even if it isn’t perfect, it will only affect those who enable it, but I am fairly confident in it. But feel free to report bugs, or fix it if you find any bugs.

**Edit: **
I am actually liking these matching rules better than the old ones.

0 Likes

#66

[quote=“facelessuser”]Ahh crap. Looks like I sucked myself back in. :smile:

The more I thought about it the easier it seemed like it would be…so I went ahead and did it.
[/quote]

I’d be lying if I said I wasn’t hoping that would happen :smiley:

[quote]
Version 1.6

  • Add setting to match only when cursor is between brackets

It is isolated with the setting, so even if it isn’t perfect, it will only affect those who enable it, but I am fairly confident in it. But feel free to report bugs, or fix it if you find any bugs.

**Edit: **
I am actually liking these matching rules better than the old ones.[/quote]

I’m going to go out and make sure I have the most recent right now!

Thanks!

P.S. Not that you need it, but you have my permission to take the weekend off!

0 Likes

#67

Small thing I noticed when testing out new bracket matching rules, is that in general, if adjacent_only is set True, internal string bracket matching no longer functions proper. So now if **adjacent_only ** is **True ** and if match_string_brackets is True, the string quote highlighting will be suppressed, but the internal string bracket matching will still be processed with the same **adjacent_only ** rules. Now I am really done, and now I am taking the weekend off :smile:.

Version 1.6.1

  • Suppress string highlighting when adjacent_only is set, but allow internal string brackets to still get highlighted with adjacent_only settings if match_string_brackets is true
0 Likes

#68

[quote=“C0D312”]I still want to do some more playing around with the icons. For now, here’s an HTML ‘tag’ icon: cl.ly/2M1x0e2g141X1Y1I1B3z

Might want to change it later, but that’s it so far.[/quote]

Looks good, Maybe we can add yet another package :smiley: “GutterIcons” and collect there some nice similar polished icons for the different sizes and possible OS.
Providing an APi or something to use the icons, then other packages use these (if they whish) and the overall application will feel better.
Like 4 different linters using the same icons for displaying errors.

0 Likes

#69

[quote=“tito”]Looks good, Maybe we can add yet another package :smiley: “GutterIcons” and collect there some nice similar polished icons for the different sizes and possible OS.
Providing an APi or something to use the icons, then other packages use these (if they whish) and the overall application will feel better.
Like 4 different linters using the same icons for displaying errors.[/quote]

It would be really easy to do. I would throw together a repository if I thought someone would use it other than me :smile:.

0 Likes

#70

[quote=“facelessuser”]Small thing I noticed when testing out new bracket matching rules, is that in general, if adjacent_only is set True, internal string bracket matching no longer functions proper. So now if **adjacent_only ** is **True ** and if match_string_brackets is True, the string quote highlighting will be suppressed, but the internal string bracket matching will still be processed with the same **adjacent_only ** rules. Now I am really done, and now I am taking the weekend off :smile:.

Version 1.6.1

  • Suppress string highlighting when adjacent_only is set, but allow internal string brackets to still get highlighted with adjacent_only settings if match_string_brackets is true[/quote]

Hm. I noticed some odd behavior, and that may have been it. I was planning on waiting until the beginning of the week before reporting it (really want you to get some rest!), but I don’t think I’ll need to now.

The new logic is just what I was wanting. Thank you very much for putting it in so quickly (and saving me from having to wrap my brain around yet another pile of code).

I did notice what appears to be incorrect highlighting involving Ruby string interpolation, but again, I’ll wait until next week to report that. And when I do, I’ll post a GitHub issue instead of mentioning it here. This thread is quite long now.

Good work, facelessuser. Keep it up (in moderation)!

0 Likes

#71

Don’t worry. You can post your issue now or later. I don’t drop everything when an issue pops up. These are hobby projects, if I am not having fun, I am not doing it. If I don’t feel up to tackling something, I wait until I do feel like it.

Some people may have an expectation that a dev should jump on an issue right away, but I just like to let people know, I will get to it when I feel like it :wink:.

I’m not making money off this, so if someone has an issue that I don’t feel like/don’t have time to get to, they have to wait or try and fix it.

Make sure you give detailed explanation if it is some syntax specific to ruby (I don’t use ruby); ideally post some example code so I can copy and test with it because I don’t know ruby syntax well. It makes it much easier than me having to hand type example code from a jpeg :smile:.

0 Likes

#72

[quote=“tito”]

[quote=“C0D312”]I still want to do some more playing around with the icons. For now, here’s an HTML ‘tag’ icon: cl.ly/2M1x0e2g141X1Y1I1B3z

Might want to change it later, but that’s it so far.[/quote]

Looks good, Maybe we can add yet another package :smiley: “GutterIcons” and collect there some nice similar polished icons for the different sizes and possible OS.
Providing an APi or something to use the icons, then other packages use these (if they whish) and the overall application will feel better.
Like 4 different linters using the same icons for displaying errors.[/quote]

I was just goofing around, but if someone else wanted to use gutter icons I coded a simple script called fancy_regions.py

[code]import sublime
from glob import glob
from os.path import exists, normpath, join, basename

REGION_STYLES = {
“solid”: 0,
“none”: sublime.HIDDEN,
“outline”: sublime.DRAW_OUTLINED,
“underline”: sublime.DRAW_EMPTY_AS_OVERWRITE
}

class FancyRegions(object):
def init(self, view):
self.view = view
self.__icon_path = “FancyRegions/icons”
self.__icons = ]
self.__icons_cached = False

def erase_regions(self, key):
    """
    Erase regions
    """

    self.view.erase_regions(key)

def add_outline_regions(self, key, regions, scope="text", icon="none", flags=0):
    """
    Add outline regions
    """

    self.add_regions(key=key, regions=regions, scope=scope, style="outline", flags=flags)

def add_underline_regions(self, key, regions, scope="text", icon="none", flags=0):
    """
    Add underline regions
    """

    self.add_regions(key=key, regions=regions, scope=scope, style="underline", flags=flags)

def add_hidden_regions(self, key, regions, scope="text", icon="none", flags=0):
    """
    Add hidden regions
    """

    self.add_regions(key=key, regions=regions, scope=scope, style="none", flags=flags)

def add_solid_regions(self, key, regions, scope="text", icon="none", flags=0):
    """
    Add solid regions
    """

    self.add_regions(key=key, regions=regions, scope=scope, style="solid", flags=flags)

def add_regions(self, key, regions, scope='text', style="solid", icon="none", flags=0):
    """
    Add regions with defined styling to a view
    """

    # Default flag settings
    options = 0

    # Check style type
    if style in REGION_STYLES:
        options |= REGION_STYLES[style]

    # Convert regions suitable for underlining if style underline
    if style == "underline":
        regions = self.__underline(regions)

    # Set additional flags if given
    if flags:
        options |= flags

    # If icon is defined and exists, set the icon path
    icon_path = ""
    if icon != "" and icon != "none":
        if self.view.line_height() < 16:
            icon += "_small"

        if exists(normpath(join(sublime.packages_path(), self.__icon_path, icon + ".png"))):
            icon_path = "../%s/%s" % (self.__icon_path, icon)

    # Apply region(s)
    self.view.add_regions(
        key,
        regions,
        scope,
        icon_path,
        options
    )

@property
def icons(self):
    """
    Get list of available icons in current icon path
    """

    if self.__icons_cached:
        return self.__icons:]
    else:
        if not self.index_icons():
            return self.__icons:]
        else:
            return ]

@property
def icon_path(self):
    """
    Return current path to icons (relative to Packages)
    """

    return self.__icon_path

@icon_path.setter
def icon_path(self, path):
    """
    Set current path to icons (relative to Packages)
    """

    file_path = path.replace('\\', '/').strip('/')
    full_path = normpath(join(sublime.packages_path(), file_path))
    if exists(full_path):
        self.__icon_path = file_path
        self.index_icons()

def index_icons(self):
    """
    Search for icons in current icon path and store results
    """

    errors = False
    self.__icons = ]
    file_path = normpath(join(sublime.packages_path(), self.__icon_path))
    if exists(file_path):
        self.__icons = [basename(png).rstrip(".png") for png in glob(file_path + "/*.png")]
        self.__icons_cached = True
    else:
        self.__icons = ]
        self.__icons_cached = False
        errors = True
    return errors

def __underline(self, regions):
    """
    Convert regions to individual empty regions for underlining
    """

    new_regions = ]
    for region in regions:
        start = region.begin()
        end = region.end()
        while start < end:
            new_regions.append(sublime.Region(start))
            start += 1
    return new_regions

[/code]

Allows you to do stuff like this: lets say you wanted to create an underlined region with the default scope and a custom icon found in the custom icon folder.

[code]
import sublime
from fancy_regions import FancyRegions

fancy = FancyRegions(sublime.active_window().active_view())
region_list = [sublime.Region(0, 6)]
fancy.add_underline_regions(‘test_region’, region_list, icon=“some_icon”)[/code]

It does common region types like solid, outline, underline, and it handles all of the custom icon stuff. You can even request a list of icons in the custom icon folder.

I could put this in a repository, but I am just not sure if anyone would actually use it or not. But I was just fooling around. :smile:

0 Likes

#73

hello, i use BracketHiglighter and i like it alot, can u maybe make this option:

default behavior in notepad++

can u add that red line, so its filling the gap between brackets .to see more clearly block where ur cursor is :smile: would be awsame <3

0 Likes

#74

Hmmm. Interesting. I was about to say that making that line would not be possible but then I realized, Yes it is. It might take some work, but with the custom gutter icons, a straight line isn’t out of the question. I personally don’t thing it’s that important of a feature but could be an interesting exercise for the gutter’s capabilities.

0 Likes

#75

I don’t think it is out of the realm of possibilities, but it does have some limitations.

[quote=“ManFromEarth”]hello, i use BracketHiglighter and i like it alot, can u maybe make this option:

default behavior in notepad++

can u add that red line, so its filling the gap between brackets .to see more clearly block where ur cursor is :smile: would be awsame <3[/quote]

To be honest, this would only really work if no_multi_select_icons was enabled. Highlighting multi-select brackets like that would just be a mess; it just wouldn’t work with how ST2 does things.

Tell you what, I will look into how good I could make it look with no_multi_select_icons enabled, and if I can get it to look decent, I might add it disabled by default.

0 Likes

#76

in this context, i was trying to recall if in previous Sublime versions the indent guides colored differently to indicate cursor location.
i was actully looking for this option a few months ago, guess it wasn’t even there, wasn’t it?

0 Likes

#77

[quote=“vitaLee”]in this context, i was trying to recall if in previous Sublime versions the indent guides colored differently to indicate cursor location.
i was actully looking for this option a few months ago, guess it wasn’t even there, wasn’t it?[/quote]

Oh yeah. @Facelessuser, settting indent guides to draw_active is essentially the same thing and a lot cleaner. So you might not want to waste your day fiddling with something that’s not really important/already implemented.

0 Likes

#78

[quote=“C0D312”]

[quote=“vitaLee”]in this context, i was trying to recall if in previous Sublime versions the indent guides colored differently to indicate cursor location.
i was actully looking for this option a few months ago, guess it wasn’t even there, wasn’t it?[/quote]

Oh yeah. @Facelessuser, settting indent guides to draw_active is essentially the same thing and a lot cleaner. So you might not want to waste your day fiddling with something that’s not really important/already implemented.[/quote]

Built in only does function blocks, not any bracket block. And trust me, it is supper easy to add (I’m not looking to spend a lot of time on anything today :smile:):

Cavet: when you space the lines further, they get further apart. But you can’t get better than this though, it is a limitation with ST2.


General Impression?

0 Likes