Sublime Forum

[solved] Add notification to input panel

#1

I use input panel to insert path. (change path in settings)

On on_change I want to show user if this path is valid. (os.paht exists)

Any Ideas how to do it?
Make text/background green/red
Add some text to begining of panel (close and reopen on on change? how can I close It?)
Other way?

0 Likes

#2

I’m v.new to this but…

self.window.active_view().run_command("hide_panel")

would/should(?) hide the panel - but this would trigger the ‘on-done’ event. I’m guessing that, as the input panel is also a View, then it would be possible to add text to it. Say adding ’ xx’ at the end of the line, until the path is found, then removing this text. But you could probably add text at the beginning of the line as well…

I’m also guessing that we can’t change the text colour in the panel :question:. Hopefully someone will confirm or deny this. Andy.

0 Likes

#3

I got the following to work - it might be helpful :sunglasses:. If I type ‘bob’ in the input panel it precedes it with 'xx '. So it would need to be modified to start with ‘Not found:’, switch to 'Found: ', replacing the text each time.

[code]import sublime, sublime_plugin

class AndyOutput(sublime_plugin.WindowCommand):
ignore = False
the_input = None
def run(self):
self.the_input = self.window.show_input_panel(‘Andy>’,’’, self.on_done, self.on_change, None)

def on_done(self, text):
	pass

def on_change(self, text):
    if self.ignore:
        return  
    try:
        if text == '':
            return
        if text-3:] == 'bob':
            edit = self.the_input.begin_edit()
            self.the_input.insert(edit, 0, 'xx ')
            self.ignore = True
            self.the_input.end_edit(edit)
            self.ignore = False
    except ValueError:
        pass [/code]
0 Likes

#4

I’ve had no response to my previous post as yet but, nevertheless, I’m pursuing this subject. The following opens the input panel beginning with the term ‘Not found:’. If I eventually type ‘bob’ then the beginning text is replaced with 'Found: '. It then reverts to ‘Not found:’ until ‘bob’ appears again. It should be easy to replace ‘bob’ with the result of a file/path search.

[code]class AndyOutput(sublime_plugin.WindowCommand):
ignore = False
the_input = None
def run(self):
self.the_input = self.window.show_input_panel(‘Andy>’,‘Not found:’, self.on_done,
self.on_change, None)
self.ignore = False

def on_done(self, text):
	pass

def on_change(self, text):
    if self.ignore:
        return  
    try:
        if text == '':
            return
        sel = self.the_input.sel()[0]    ######### AttributeError
        sel_line =self.the_input.line(sel)
        
        if text-3:] == 'bob' and text[0:3] == 'Not':
            edit = self.the_input.begin_edit()
            self.the_input.replace(edit, sublime.Region(sel_line.begin(),
                sel_line.begin()+10), 'Found:    ')
            self.ignore = True
            self.the_input.end_edit(edit)
            self.ignore = False
        elif text[0:5] == 'Found':
            edit = self.the_input.begin_edit()
            self.the_input.replace(edit, sublime.Region(sel_line.begin(),
                sel_line.begin()+10), 'Not Found:')
            self.ignore = True
            self.the_input.end_edit(edit)
            self.ignore = False
    except ValueError:
        pass[/code]

I do get an AttributeError: ‘NoneType’ object has no attribute ‘sel’ - at the line indicated, but the code still works (oddly). But… I’m new to Python :smiley:

0 Likes

#5

The attribute error in my recent post is really bugging me. It only occurs when the file is first run. If anyone has an idea why this is happening, that would be great :smiley:

0 Likes

#6

You can use sublime.status_message() to do this, which is what happens in the find panel if an invalid regex is entered

0 Likes

#7

Hello, and thank you.

Still learning, so I haven’t wasted my time :laughing:. I still need to know about this attribute error, but I figure I need to gen up on static and instance variables/attributes a bit.

Regards, Andy.

0 Likes

#8

The attribute error likely comes from ‘the_input’ being None, as on_change may be getting called once before show_input_panel returns

0 Likes

#9

Hello and thank you. I shouldn’t have to initialize to None, so I’ll re-examine my code a bit later.

Regards, Andy.

0 Likes

#10

I can get round my error with a simple ‘except: return’, which ignores the error first time around, but this is not good.

How can I obtain the Region of the input panel? Currently, I’m using a reference to the panel as ‘the_input’ but this creates the problem just discussed:

def on_change(self, text): self.sel = self.the_input.sel()[0] # the_input refers to the input panel (a self-reference)
How can I amend this to refer to the input panel, without using ‘the_input’ pl?

I appreciate that status_message() is the way to go - it’s intended for this purpose :smile:. But I know that it’s possible to amend (edit) the input panel’s text. But ‘self.view.sel()[0]’ doesn’t work?!

Andy.

0 Likes

#11

No worries :wink: although I’m still interested to know how to refer to the input panel’s Region directly (within the on_change event)…?

Using default text (‘Not found:’) in

self.the_input = self.window.show_input_panel('Andy>','Not found:', self.on_done, self.on_change, self.on_cancel)
triggers the on_change event, and then referring to ‘the_input’ (within the event) causes an error because it doesn’t yet exist. If I move the reference to ‘the_input’ further into the code then the problem doesn’t arise:

def on_change(self, text): if self.ignore: return try: if text == '' or len(text) == 0: return if text-3:] == 'bob' and text[0:3] == 'Not': self.sel = self.the_input.sel()[0] self.sel_line =self.the_input.line(self.sel) edit = self.the_input.begin_edit()
Alternatively, I could create a flag called ‘first_call’ and return directly if this is True.

When I’ve got this sussed I might write a short intro. guide myself (as there doesn’t seem to be a straight-forward one available). Andy.

0 Likes

#12

Thanks to everyone.

class SetMabPathCommand(sublime_plugin.TextCommand):
    def __init__(self, *args, **kwargs):
        sublime_plugin.TextCommand.__init__(self, *args, **kwargs)
        self.settings = sublime.load_settings('Mab.sublime-settings')

    def run(self, edit, key='', val='', save=True):
        path = self.settings.get('mab_path')
        self.input = sublime.active_window().show_input_panel('input',
            path, self.on_done, self.on_change, None)
        self.on_change(path) # call it to colorify input
    
    def on_done(self, text):
        if os.path.exists(text):
            self.settings.set('mab_path', text)
            sublime.save_settings('Mab.sublime-settings')
        else:
            sublime.error_message('Path %s does not exists' % text)
    
    def on_change(self, text):
        if os.path.exists(text):
            scope = 'constant'
        else:
            scope= 'constant.character.escape'
        self.input.add_regions('regs', [sublime.Region(0, self.input.size())], scope)

Note: If I try to open input when input opened I get traceback in console.

AttributeError: 'SetMabPathCommand' object has no attribute 'input'

But I do nothing. I need only one input at single time.

0 Likes

#13

That sounds very much like the error I was discussing.

0 Likes

#14

[quote=“agibsonsw”]

That sounds very much like the error I was discussing.[/quote]

Yes. But it appears only if panel opened and does not affect opened panel.

Pseudocode:

class Plugin(sublime_plugin....):
    input = None

def run(....)
    if not self.input:
         self.input = show_input(....)

def on_close_on_done():
     .....
     self.input = None

def on_change(...):
   if self.input:
       dooo

[code]class SetMabPathCommand(sublime_plugin.TextCommand):
_input = None
settings = sublime.load_settings(‘Mab.sublime-settings’)

def run(self, edit, key='', val='', save=True):
    if not self._input:
        path = self.settings.get('mab_path')
        self._input = sublime.active_window().show_input_panel('input',
            path, self.on_done, self.on_change, self.on_close)
        self.on_change(path)

def on_done(self, text):
    if os.path.exists(text):
        self.settings.set('mab_path', text)
        sublime.save_settings('Mab.sublime-settings')
    else:
        sublime.error_message('Path %s does not exists' % text)

def on_close(self):
    self._input = None

def on_change(self, text):
    if self._input:
        if os.path.exists(text):
            scope = 'constant'
        else:
            scope= 'constant.character.escape'
        self._input.add_regions('regs', [sublime.Region(0, self._input.size())], scope)

[/code]

0 Likes