forked from aziz/SublimeFileBrowser
-
Notifications
You must be signed in to change notification settings - Fork 0
/
prompt.py
122 lines (99 loc) · 3.74 KB
/
prompt.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sublime
from sublime import Region
from sublime_plugin import TextCommand, WindowCommand
import os
from os.path import join, expanduser
ST3 = int(sublime.version()) >= 3000
NT = sublime.platform() == 'windows'
if ST3:
from .common import sort_nicely
else:
from common import sort_nicely
map_window_to_ctx = {}
def start(msg, window, path, callback):
"""
Starts the prompting process.
"""
if not(path.endswith(os.sep) or path == os.sep):
path += os.sep
path = expanduser(path)
map_window_to_ctx[window.id()] = PromptContext(msg, path, callback)
window.run_command('dired_prompt')
def isdir(u):
'''alas, this is really silly'''
if NT and any(v for v in (u'\\', u'/') if v == u):
return False
else:
return os.path.isdir(u)
def valid(value):
if not isdir(value):
sublime.error_message(u'FileBrowser:\n\nDirectory doesn’t exist:\n%s' % value)
return False
else:
return True
class PromptContext:
def __init__(self, msg, path, callback):
self.msg = msg
self.path = path # The path we are completing. This is updated as the user types, so it will be an invalid path at times.
self.callback = callback
class DiredPromptCommand(WindowCommand):
"""
An internal-only command that separates prompt handling from external commands since each
tab completion requires another command.
A prompt context must already be registered in map_window_to_ctx when this is executed.
"""
def run(self):
self.ctx = ctx = map_window_to_ctx[self.window.id()]
pv = self.window.show_input_panel(ctx.msg, ctx.path, self.on_done, None, None)
pv.settings().set('dired_prompt', True)
def on_done(self, value):
if not valid(value):
return self.window.run_command('dired_prompt')
self.ctx.callback(value)
class DiredCompleteCommand(TextCommand):
"""
An internal command executed when the user has pressed Tab in our directory prompt.
"""
def run(self, edit):
self.edit = edit
self.prompt_region = Region(0, self.view.size())
content = expanduser(self.view.substr(self.prompt_region))
path, prefix = os.path.split(content) if not isdir(content) else (content, '')
if not valid(path or content):
return
completions = [n for n in os.listdir(path) if n.upper().startswith(prefix.upper()) and isdir(join(path, n))]
sort_nicely(completions)
common = os.path.commonprefix([f.upper() for f in completions])
new_content = ''
if not completions:
return sublime.status_message('No matches')
if len(completions) == 1:
new_content = join(path, completions[0]) + os.sep
elif common and common > prefix:
new_content = join(path, common)
if new_content:
self.fill_prompt(new_content)
else:
self.completions = completions
self.path = path
self.w = self.view.window() or sublime.active_window()
return self.w.show_quick_panel(completions, self.on_done)
def on_done(self, i):
if i < 0: return
content = join(self.path, self.completions[i]) + os.sep
if ST3:
ctx = map_window_to_ctx.get(self.w.id())
ctx.path = content
self.w.run_command('dired_prompt')
return
else:
self.fill_prompt(content)
self.w.focus_view(self.view)
def fill_prompt(self, new_content):
self.view.replace(self.edit, self.prompt_region, new_content)
eol = self.view.size()
self.view.sel().clear()
self.view.sel().add(Region(eol, eol))
return