Sublime Forum

Interface Suggestions Discussion: Style console output

#1

Continuing the discussion from Interface Suggestions:

Iirc there was a theme that added syntax coloring to the console a while back. I’m not sure how they did it though? Probably some widget settings stuff. This is also used to highlight regular expressions in the find panel, but I don’t know how ST knows to only color the find panel and not any of the other widgets. Hint’s welcome.

If this was eventually added as a default feature (which I’m strongly in favor of), I’d like to work on a REPL Python syntax definition after I patched the Python syntax to properly distinguish between expressions and statements.
Just mentioning this.

5 Likes

Can I change the font and color for the built in console?
[BUG ST2/3] set_syntax_file() clear 'is_widget' setting
#2

I’m not sure if this is what you’re talking about but, FWIW, this theme claims a “highlighted console.”

2 Likes

#3

Ah yes, thanks. That’s exactly the one I was thinking about.

It does indeed seem that it references the syntax definition in a Widget.sublime-settings file. I assume that also applies to the find panel being highlighted as Python code then?

Edit: Just added it to a portable ST instance. Doesn’t seem to work. Opened an issue: https://github.com/Kronuz/Kronuz-Theme/issues/2

0 Likes

#4

Out of a sudden, it started working after a reboot. Don’t ask.

Unfortunatly (and as expected), it also highlights the find text when regular expression search is disabled:

0 Likes

#5

 
Seems like an easy fix:

class EventListener( sublime_plugin.EventListener ):
	
	def on_activated_async( self, view ):
		update_FindPanel_Syntax( view )

	def on_modified_async( self, view ):
		update_FindPanel_Syntax( view )
		
def update_FindPanel_Syntax( view ):
	if  view.settings().get( "is_widget" ) \
	and sublime.active_window().active_panel() == "find":
		if view.match_selector( 0, "source.regexp" ):
			view.settings().set( "syntax", "Packages/Regular Expressions/RegExp.sublime-syntax" )
		else:
			view.settings().set( "syntax", "Packages/Text/Plain text.tmLanguage" )

 
The only issue would be that neither of the listeners will affect the following case:

  • open Find panel while RegEx mode is disabled
  • type in RegEx code first
  • enable RegEx mode without making any further modifications
1 Like

#6

Ah right, we have an API for determining the active panel now. Unfortunately the replace and find_in_files panels contain more than one view.

Instead of listening to on_modified you could listen to on_window_command though, since toggling the regular expression button is implemented as a command (toggle_regex).

0 Likes

#7

I wanted to know which panels exactly the Widget.sublime-settings files affect. There is zero documentation on that, besides this one post (and thread), which basically says “all widgets”, so I did some testing.

The following views have the “is_widget” setting set:

  • views in the find, replace, find_in_find panel
  • the console input (likely output too)
  • input panel
  • command palette
  • goto anything
  • quick panel

The following views do not have it set:

  • normal views
  • output panels

And a quick test reveals that they are indeed affected by the syntax setting:

I suppose setting the console syntax via Widgets.sublime-settings is possible but infeasable then, unless we want to “unset” the syntax for all views that are not in the console panel.


Issues I have with this system:

  • Syntax highlighting between normal views and regular expressions (in the find panel) or potentially Python code in the console will be different. Even if themes do not define a color scheme in their widgest settings file, the default theme defines one in a Widgets.sublime-settings, which is always considered due to not being named Widgets - Default.sublime-settings (from the theme being named “Default”).
  • Setting the syntax for “just the console” is not possible. You get all or nothing.
3 Likes

#8

Update: Output panels are inconsistent. By default they actually do have is_widget set, but sometimes they do not. Notably, the “exec” panel after a build was performed:

>>> exec = window.create_output_panel("exec")
>>> exec.settings().get('is_widget')
True
>>> sublime.log_commands(True)
command: build
Running python -u "C:\some\file.py"
command: show_panel {"panel": "console", "toggle": true}
>>> exec.settings().get('is_widget')

The LaTeXTools package build system, which re-uses the “exec” output panel for its custom build command, does not unset the is_widget setting.

I could narrow it down to self.output_view.assign_syntax() being the culprit, as that seemingly turns the output panel into a “real view”, which also sets the gutter and other settings by default, which is why in exec.py most of these settings are explicitly disabled (notably gutter and line_numbers).

… Why?

I would also like to have an explanation for these comments:

if not hasattr(self, 'output_view'):
    # Try not to call get_output_panel until the regexes are assigned
    self.output_view = self.window.create_output_panel("exec")

[...]

# Call create_output_panel a second time after assigning the above
# settings, so that it'll be picked up as a result buffer
self.window.create_output_panel("exec")

The settings are also not reset upon calling create_output_panel again, despite all content being erased.

2 Likes

API Suggestions
Build Results panel: How to hide the ruler?
#9

I’ve seen this as well. On day I was pretty sure I should be checking for is_widget in the output panel, and then another day debugging I see that output panel doesn’t actually have is_widget. I thought I was just crazy.

0 Likes

#10

in my “extensive” testing (opening and closing ST a few times on Windows and Linux), I discovered that, at least for the 1st ST window, the view.id() of the console input box is always 4. I’m sure I read somewhere (I think on this forum, but I can’t find it again now) that id’s under 10 are reserved for widgets.

therefore:

import sublime
import sublime_plugin


class SetConsoleSyntaxEventListener(sublime_plugin.EventListener):
    def on_activated_async(self, view):
        if view.id() == 4:
            if view.settings().get('syntax') == 'Packages/Text/Plain text.tmLanguage':
                view.assign_syntax('Packages/Python/Python.sublime-syntax')
                view.settings().set('gutter', False)
                view.settings().set('is_widget', True)
2 Likes

#11

Ah yeah, I did that too a long time ago in ST2. It seemed consistent between restarts, so it is probably due to their creation order. That could be a good way to specifically target the console view, but will not work for any windows opened after that, unless we find a way to determine the first view id in a newly opened window.

So yes, it might be possible with hacks, but I can’t say for sure without experimenting.

(unfortunately I do not remember where I saved my observations, if at all)

2 Likes

#12

I’ve updated my little plugin to set the syntax on the regex replacements input box too, because Regex Format Widget isn’t a string that exists in the ST binary:

import sublime
import sublime_plugin


view_syntaxes = {
    4: { 'name': 'ConsoleInput', 'syntax': 'Python/Python.sublime-syntax' },
    9: { 'name': 'FindAndReplace_ReplaceInput', 'syntax': 'PackageDev/Syntax Definitions/Regex Replacement.sublime-syntax' }, # https://github.com/SublimeText/PackageDev/pull/88
    13: { 'name': 'FindInFiles_ReplaceInput', 'syntax': 'PackageDev/Syntax Definitions/Regex Replacement.sublime-syntax' } # NOTE: ST doesn't currently support Boost regex replacement syntax in these panels: https://github.com/SublimeTextIssues/Core/issues/1524
}

class ConsoleEventListener(sublime_plugin.EventListener):
    def on_activated_async(self, view):
        if view.settings().get('syntax') == 'Packages/Text/Plain text.tmLanguage' and view.settings().get('is_widget', False):
            if view.id() in view_syntaxes:
                syntax = view_syntaxes[view.id()]['syntax']
                view.assign_syntax('Packages/' + syntax)
                view.settings().set('gutter', False)
                view.settings().set('is_widget', True)
                
                settings = sublime.load_settings('Widget.sublime-settings')
                view.settings().set('color_scheme', settings.get('color_scheme'))

I guess one could change it to read a named settings file instead, corresponding to which widget was activated (a horrible hack, I know, due to not being able to reference a view by id), to make it more flexible, but as there is no way to get a list of defined settings I kept it this way for my purposes, to avoid confusion.

0 Likes

#13

You can reference views by id. Just create a new sublime.View instance with the id as its only parameter.

2 Likes

#14

omg! I never knew that! thank you so much sir! (or, more likely, I saw it in sublime.py a long time ago but never considered it useful so promptly forgot about it again)

0 Likes

#15

new code is:

import sublime
import sublime_plugin

view_syntaxes = {
    4: { 'name': 'ConsoleInput', 'syntax': 'Python/Python.sublime-syntax' },
    9: { 'name': 'FindAndReplace_ReplaceInput', 'syntax': 'PackageDev/Syntax Definitions/Regex Replacement.sublime-syntax' },
    13: { 'name': 'FindInFiles_ReplaceInput', 'syntax': 'PackageDev/Syntax Definitions/Regex Replacement.sublime-syntax' }
}

#def plugin_loaded(): # doing it here makes the textboxes vertically massive!
class ShowPanelListener(sublime_plugin.EventListener):
    def on_post_window_command(self, window, command, args):
        if command == 'show_panel':
            for view_id in view_syntaxes:
                view = sublime.View(view_id)
                syntax = view_syntaxes[view_id]['syntax']
                view.assign_syntax('Packages/' + syntax)
                view.settings().set('gutter', False)
                view.settings().set('is_widget', True)
                
                settings = sublime.load_settings('Widget.sublime-settings')
                view.settings().set('color_scheme', settings.get('color_scheme'))

but it still only works for the 1st ST window :wink:

4 Likes

#16

Be warned, loading a syntax definition to use on the console that creates console output will cause a deadlock.

2 Likes

#17

this is only altering the console input textbox, @wbond, not the console output/log textbox - does that make a difference? or can it still deadlock? I’m guessing this is why its not assigned the syntax by default?

0 Likes