|
本帖最后由 Mozilla 于 2020-5-3 16:02 编辑 $ b+ s1 [1 F/ E
" Y. o" o8 @% Z! i8 x, E
sublime_text3组件Sublime_plugin源代码免费分享!请不要翻译此页!
" a0 Q. A, X# W5 S( E" f- import imp2 T) N9 D! ?* r. X6 V" t. p9 Q
- import importlib0 z4 U) w. G0 Y# q/ Z
- import os
7 p/ r s6 }9 g! I - import sys6 o: w& p6 X6 n7 A
- import threading
2 }( Y& O) a5 _* e; a7 K - import time2 |8 {9 n+ s( `3 d- R, j2 s! i
- import traceback
k- `4 z [& S% Z - import zipfile
0 W8 O! R# b. l" r7 |' S/ C
; G: e: V; a1 o4 C3 y- import sublime
0 H* [% R' g1 [9 h% Y( e - import sublime_api
% J( K2 P0 V3 Y) ~ - ; B2 x# i. x h2 P# h" j
- ) K( I* q8 O) c) w1 @0 p% i8 Z
- api_ready = False$ M% A. Z4 O- V& ~2 D# U; L+ M
% O ?& c P. f/ K6 J; ?7 {5 N- application_command_classes = []' A* W" M) _% `$ b. q. k* ?7 Q
- window_command_classes = []
1 N) Z; [5 [* q) E' y; A' p - text_command_classes = []0 ^3 r; B4 @& U6 k3 x
( ?) D9 B3 D3 m- view_event_listener_classes = []4 c" `6 o$ B: K6 D4 ~6 M) v- R3 Z+ l
- view_event_listeners = {}
9 H; c" W+ S: Y9 o' N7 S- T ^1 ~0 x
# P: p& x. p& ~# ?# O0 G# g: X" D- all_command_classes = [
9 U% F. `' H f8 h2 }' s* ^2 O - application_command_classes,8 a" Q j) p7 B R+ ^! A' p; A
- window_command_classes,
* N, o% Q& i2 z" F/ ]4 t - text_command_classes]
8 V8 m0 d6 }; X& U2 i - b2 W; P# x" y0 d
- all_callbacks = {( ^ H/ K( O F$ o0 U
- 'on_new': [],3 o q' p: j9 G% F$ f
- 'on_clone': [],
+ s; {& n* c% D( z" W0 ~ - 'on_load': [],5 s+ n- {# D4 T( m1 [
- 'on_pre_close': [],
9 ?/ P" f( Y% Q1 L7 R - 'on_close': [],
5 R, ?" Z. D( X1 ?$ G! v( ~. ]& E% W - 'on_pre_save': [],% D# ?: k+ I9 z1 [
- 'on_post_save': [],
& P2 m( k' ?7 I6 Y - 'on_modified': [],
, T0 P& K# f$ t5 \+ E- i1 S9 D B" j - 'on_selection_modified': [],
/ K; ^2 K) k, Y* y' z - 'on_activated': [], S" P) v: ?2 ^/ E/ j/ B: ]
- 'on_deactivated': [],
' D) a1 n4 w' P1 ~& M6 I - 'on_query_context': [],; ~9 ~1 ~2 T; H4 I+ _( `& ~1 n
- 'on_query_completions': [],: U- n. ^9 `+ a. y4 Q3 S
- 'on_hover': [],
6 e& k6 D J# t' w. }6 @# S - 'on_text_command': [],4 [2 j0 u5 L# v( H; e0 t. k
- 'on_window_command': [],
4 J2 O* Q6 w; e4 H+ S - 'on_post_text_command': [],- d/ m; Z1 Y$ C% O5 q0 x
- 'on_post_window_command': [],
$ h( A, X# X9 q9 }% p8 s. v7 ? - 'on_modified_async': [],
8 C' O; {: b& J5 B0 h - 'on_selection_modified_async': [],! v& k1 M+ {- r x8 w& m
- 'on_pre_save_async': [],1 v1 d: z" [# B: L w# v) M
- 'on_post_save_async': [],; n% H$ V) r c P9 d
- 'on_activated_async': [],5 m* o) k) m( f8 z+ }
- 'on_deactivated_async': [],
" Z# C9 _; B# w6 H - 'on_new_async': [],
! b% P. f- v" u8 @ H - 'on_load_async': [],
, T/ A3 Y, G" @4 e* {5 W4 z8 ` - 'on_clone_async': []}' j) q: p% f& k8 _: ~
3 `% d' ?2 E8 s0 T- pending_on_activated_async_lock = threading.Lock()
+ `3 }- l" S& T1 r/ M
9 `: r2 N/ z2 ?) j1 x: z- pending_on_activated_async_callbacks = {1 k& O+ l! z- W' |8 o
- 'EventListener': [],4 h! f7 H- U. S) M' M* ^7 s e1 R
- 'ViewEventListener': []}) P* T. f& U; \/ `- i5 v% O5 T
6 S7 G/ a( o+ U. e0 C) z5 Q. L- profile = {}
- C; r6 o5 s4 Q" d - 9 ]) I) H3 }2 ]) ]7 Q1 _
- ( ?& R) ]# c0 c/ G
- def unload_module(module):4 [7 {+ l0 s/ }8 Z
- if "plugin_unloaded" in module.__dict__:" @) y" r6 B1 {9 e# J* n* N% H4 u
- module.plugin_unloaded()! z$ g9 D' g# M' W% r& J6 V3 }
- # Check unload_handler too, for backwards compat2 L7 V+ [) }. B [& T# Y) Z
- if "unload_handler" in module.__dict__:
( g2 k% z) `4 e6 }1 B% R6 { - module.unload_handler()
* E+ n( [4 y7 F, l- w' s
, P' H9 M# Y" w- # Unload the old plugins3 I0 U( b: i( l$ I2 i; E
- if "__plugins__" in module.__dict__:
" s9 ^0 n: T/ e: x - for view_id, listener_instances in view_event_listeners.items():
3 H9 T% A4 |) Y$ ] K: C% V - for vel in listener_instances[:]:
) j. O- C. L' A6 t+ j* n7 u - if vel.__class__ in module.__plugins__:
. y, r! a a& X$ e6 l: h& n4 \5 e* s - listener_instances.remove(vel)
) D$ q" i7 Y( i2 d5 t
+ {! l: O; l! p N# ]- for p in module.__plugins__:* P7 y3 k# y, Q9 h" g0 E }# M# D
- for cmd_cls_list in all_command_classes:
1 L( W( B: q/ z6 X - try:
! @0 o8 j6 u3 I! c/ E - cmd_cls_list.remove(p), |! p7 T9 J2 D6 x$ i
- except ValueError:9 u4 l6 C% ~' u* G: u, r8 I1 M) K: W
- pass
% Y/ p, `7 S. Q2 b% I9 V/ o3 P: ] - for c in all_callbacks.values():
1 q4 u: p% W/ E: J- g7 T0 T8 R& S - try:
3 J7 ]3 R8 R+ d7 c0 _: P - c.remove(p)1 x5 d# _5 P( {: i |8 _% T$ T/ }
- except ValueError:
% q7 r2 y7 R: Q- b) f. B - pass
( u9 y& s7 C4 C, @# T6 ? - * w& a2 B [4 y5 I& a
- try:
- l6 g$ Q$ m W+ [3 ~ - view_event_listener_classes.remove(p)
! Q+ d3 q3 d1 G0 ~* Q+ e `( j$ y - except ValueError:
* ^/ x1 I0 k0 Y9 q - pass
0 Z( n# C4 c* V3 B/ `' A7 Z - : [! \# K/ R! B5 f
7 y6 F+ Z7 Q7 A3 J7 [5 K, D: J- def unload_plugin(modulename):
- [ i& J' b1 W; u8 y6 E/ _ - print("unloading plugin", modulename)8 `# D6 d4 |! k' W* U
- # B) {/ S- W2 ]' \. ]
- was_loaded = modulename in sys.modules
$ m* P2 d6 j0 p& ?; P2 V) z. e* [ - if was_loaded:2 `: G6 S) X5 ^1 h7 t0 H! l* D
- m = sys.modules[modulename]) b# R7 n2 w# S1 _1 S! i" D
- unload_module(m)2 g4 J9 h8 H! }3 z2 k
- del sys.modules[modulename]
6 _0 D, U% |- w* o% r
4 R& L. K e& x5 `
# s0 \: W" @" X7 i, n$ a- def reload_plugin(modulename):1 t. K8 ?1 h! z, |$ @: C
- print("reloading plugin", modulename)& K# y5 [/ m7 e7 b1 m) G5 R
- ; p6 U2 [7 M1 g! B
- if modulename in sys.modules:
( A$ F# D6 M: m1 o3 j" O" | - m = sys.modules[modulename]
( D0 B2 l5 L8 |9 a; |% y* n - unload_module(m)2 \. G3 Q2 U0 w' u, Q4 i1 M
- m = imp.reload(m)/ W B- I( s$ ]) y$ c
- else:& w2 {) |3 j A- H& D9 x* T2 ^
- m = importlib.import_module(modulename) O. {' G g; ~9 o0 f$ I0 c9 m
@6 L0 X. m* X& e8 m7 M' v7 a1 e- module_plugins = []& T0 V6 ]: z* {9 r, v
- on_activated_targets = []! V2 S0 G) t/ C4 ]6 a3 z! l. f# L
- vel_on_activated_classes = []8 y) I1 O L9 D# w$ A% H1 M$ o
- el_on_activated_async_targets = []& P3 y) k9 \1 M5 U4 N8 Z$ \
- vel_on_activated_async_targets = []% G, E; L/ \6 C- ?
- module_view_event_listener_classes = []
# D" s$ g/ i+ E: `. A - for type_name in dir(m):, O' A0 ~% c5 I: w
- try:; h% W( |* }& u$ V
- t = m.__dict__[type_name]& g% p4 Q( u' N' w" g" S! s. b5 F
- if t.__bases__:0 g# J* L/ c& f/ s3 M
- is_plugin = False
5 y% d& g$ I5 ~/ f6 ^, q2 K - if issubclass(t, ApplicationCommand):
, v4 ]- N, C! D' e% F6 B, m - application_command_classes.append(t)
" [9 b7 t8 n' ], N x0 K4 U - is_plugin = True P' x' a; a' d
- if issubclass(t, WindowCommand):3 Z. e( I6 V9 b
- window_command_classes.append(t)
2 b. P5 {5 v3 K: f+ N+ ~1 D, |4 } - is_plugin = True
# m3 L0 Y7 \4 T3 p2 b( Z$ {* ~ - if issubclass(t, TextCommand):% F* C$ T% j- C) M# X
- text_command_classes.append(t)$ \" I1 [: ]& A9 f, I6 s
- is_plugin = True
9 @- m7 X0 G+ N1 g1 S( E& J
1 M0 c2 W& r3 I) Z, ^& u- if is_plugin:% C9 n; Q- Z! Q: i5 c
- module_plugins.append(t)
' I1 G& q8 H8 N! b3 b3 x - 9 W, l0 W. H0 j9 [4 ~
- if issubclass(t, EventListener):. [3 m) \; s' K
- obj = t()
3 b( K7 H/ z. d0 y) b' { - for p in all_callbacks.items():
% ^# M* @7 n, L, _ - if p[0] in dir(obj):8 F9 f* L3 _& L! s* q: `4 b) L
- p[1].append(obj)/ J2 e" [% ~$ t% O
- 1 D5 R1 V3 A' x, H0 d
- if "on_activated" in dir(obj):
$ B# H; A3 {# h* m x! x4 M( D& r - on_activated_targets.append(obj) o. ]/ s# z% E7 G& X! D g
- ( T+ E4 W+ k/ v% y& T
- if "on_activated_async" in dir(obj):8 E7 l& _3 ~# Q0 R2 {
- el_on_activated_async_targets.append(obj)
2 v9 d% s* {3 r( R/ s0 k9 ~+ E% P
% L8 J5 a; }/ ^& E( @! K( i- module_plugins.append(obj)$ F: _6 m% N2 p$ h
) P5 K% s6 U E$ ?! j7 d( X- if issubclass(t, ViewEventListener):
& `* X0 Z# N1 t- b - view_event_listener_classes.append(t)
0 g* J! X k, q4 A, s - module_view_event_listener_classes.append(t)
, M" t. j! W$ g" U: o0 `+ W - if "on_activated" in dir(t):2 A! j6 w; u: L1 B6 l
- vel_on_activated_classes.append(t)9 w3 s1 X: a' O2 ~1 E9 D6 p
- if "on_activated_async" in dir(t):
6 H/ M m5 x3 n& Y8 ?5 w! | - vel_on_activated_async_targets.append(t)' C) o! R: }# u; d: u+ v8 A, @
- module_plugins.append(t)
; `. H. b+ x0 G! ` - : I" ?% N: v- {
- except AttributeError:( P+ V( _) l- ^9 F
- pass$ D; S' R* B) ?1 @
- " `. k+ j4 w0 e- }, ]& K1 J* e
- if el_on_activated_async_targets or vel_on_activated_async_targets:
; L& `) ^# l$ y - with pending_on_activated_async_lock:
3 C# J5 Q+ i. K4 E6 X - pending_on_activated_async_callbacks['EventListener'].extend(
! O1 `3 Q! x3 A. [3 X4 o5 D+ r - el_on_activated_async_targets3 E; h) N. U# M5 n
- )2 D8 S( x! B4 N3 a2 G
- pending_on_activated_async_callbacks['ViewEventListener'].extend(
; [* b/ E) t4 L - vel_on_activated_async_targets
3 {- u4 {& ?; [3 y& S, V8 \+ h - )6 s2 R9 _8 v2 m2 w
- ! X. V4 J( Q- A/ x: D
- if len(module_plugins) > 0:0 `" a) F/ g( ]0 I$ M
- m.__plugins__ = module_plugins8 k2 V7 N: s& ]5 H- G: N3 t* Z
^3 N* S! W/ J' T/ z& l- if api_ready:
7 Y- Y/ K3 | I. ?4 q6 a+ a - if "plugin_loaded" in m.__dict__:
1 M6 X7 F! V5 T2 ]% A$ d - try:& } m( j1 U2 H, M P. {
- m.plugin_loaded()
, {8 a" L; z( { Z7 v - except:
- Z# u7 J" d( Y/ _2 W) F7 e$ H - traceback.print_exc()
4 L( O! i9 `" Q5 F - * ^- c- J; a0 R5 G1 z* |
- # Create any require ViewEventListener objects1 h: z% g* n' G: p5 D s
- if len(module_view_event_listener_classes) > 0:% J2 H) R G1 v/ b' ^
- for w in sublime.windows():
B8 o' n4 g2 Q; C5 a* y ]6 Q - for v in w.views():
2 ?3 C8 z; A0 a2 ` - create_view_event_listeners(4 Z9 B8 M/ \% D+ J# F8 M8 n9 a
- module_view_event_listener_classes, v); Q5 K! G1 y B1 W! V8 ^
- ?2 x% l9 X' i- # Synthesize any required on_activated calls
8 Z; G) n. D5 N* {# {8 R! P - w = sublime.active_window()
1 W7 _" h7 [: a# W9 b - if w:
2 D, } ]. J/ d9 r( [% c - v = w.active_view()
; E5 C: G2 Z) K) J5 Q" m - if v:
. m7 z6 r/ p; R( F - for el in on_activated_targets:
2 i2 X, V9 M5 S b7 c0 b) o* I1 j: ` - try:
p; L, V1 I* O# p }/ e6 t2 J - el.on_activated(v)
+ M/ j8 M: J1 D) P6 O; ~4 c$ H5 n - except:
7 A1 h/ Q: ^7 C: u - traceback.print_exc()2 H C0 A0 B, ^# b X
5 ]+ R0 J- E; k5 h- for vel_cls in vel_on_activated_classes:
5 _. Z: C" U+ j! U; a# R - vel = find_view_event_listener(v, vel_cls)
/ }% y$ y' H4 R9 s! O - if not vel:6 ~0 k |% l `# Q+ v: L. V+ s/ _# u
- continue8 C7 z' n5 I% Q+ m4 c
- try:: n3 V; L; B! k
- vel.on_activated()3 \# V( t2 R! |* M
- except:& D0 Y( ]! Q1 o
- traceback.print_exc()
2 v' N- I) a" G - ! m8 {& |" u" \0 l- S- ]( J% T
- 9 J- S) i; G! I5 X6 S" d u- Z% V/ i1 t% n
- def synthesize_on_activated_async():" n0 ^/ s& h. H9 c) R/ Y
- if not api_ready:: G" q6 ^/ J( s
- return! o- z7 b ?0 i# F, J
4 s7 t* `) `/ J1 D( O- with pending_on_activated_async_lock:
{3 _: [6 [5 }1 c" D) {" s* _ - els = pending_on_activated_async_callbacks['EventListener']! H( U( _; }1 V3 X" ~/ e0 c+ C
- vels = pending_on_activated_async_callbacks['ViewEventListener']' v( S: n- t; T+ n2 U }" ?
- pending_on_activated_async_callbacks['EventListener'] = []& @4 K6 z) S, R/ z9 ~/ h4 ?
- pending_on_activated_async_callbacks['ViewEventListener'] = []
& F7 r1 V8 t% f4 U - # ~( H8 V$ ^0 \ f+ H8 l! d
- for el in els:. w9 Q+ X! N l/ R; B
- w = sublime.active_window()
( D" I, J+ I* X, W* ~2 h8 d) v0 E - if not w:& F3 i. I, K* {
- continue
- U9 y! g$ N) s" i/ M* w6 p5 [ - v = w.active_view()
, ]* s/ ]/ U) N5 y - if not v:! N k' d. S) g. |
- continue
+ E1 c8 j, z4 o: O+ a r3 ? - try:4 Y- v+ o$ R) W( `
- el.on_activated_async(v)
( U, E+ d2 w/ h4 M - except:! b8 u5 I/ v6 S, F B0 L" L6 g
- traceback.print_exc()' `1 |: Z$ J7 e
- Y$ m5 d* o' _) ~9 y
- for vel_cls in vels:4 o, G6 F5 `( S7 {5 O" \7 ?
- w = sublime.active_window()' n* |1 {3 n3 d- E( `% g
- if not w:# b3 q9 J1 e2 b% ^1 k3 D
- continue+ D& Q! g, ^4 B; S' o, w) V }
- v = w.active_view()
r/ Y- C6 z! D; N8 h& u - if not v:
: L( M* c0 h: ~) D7 ? - continue$ A% l2 D0 z, G; X. A' z! `2 N
- vel = find_view_event_listener(v, vel_cls)
5 \, ~$ H# Z$ P4 o" ]3 g. e) \ - if not vel:
' l' g$ \8 I5 D2 z$ \ - continue( b5 ?. N9 U/ O; q
- try:
9 H6 f+ u. H2 }: c) T - vel.on_activated_async()
9 i y7 m5 S4 y' [) u% A9 h - except:
) ]& E6 j# R! J" A% F5 g7 h - traceback.print_exc()* K) J+ \; W( E3 _' Y5 U' n
' k$ j) @. r8 ]1 z0 V
- U3 \) q) J! r0 k' k5 z6 o o- def create_application_commands():' m" l$ ?6 f5 N! U& a
- cmds = []
3 h: \2 F1 e T9 D/ t! X - for class_ in application_command_classes:
/ T: D/ e% v' w; o1 k, I, g - cmds.append(class_())
, V# k; f F! K: ?6 a+ Y! q: @ - sublime_api.notify_application_commands(cmds)# P9 }" H# F' h' U# X
4 `, i2 W0 G2 t3 D5 ?
9 z4 ]0 B, G( v- def create_window_commands(window_id):
; `$ C3 S2 M; b' Q/ V - window = sublime.Window(window_id)- c4 o! |; T$ N, E/ I, o
- cmds = []) `. g/ j3 W g
- for class_ in window_command_classes:
' d0 @& o9 I$ c) h+ m - cmds.append(class_(window))" ?2 {2 ]( f% F9 m% M! b9 k
- return cmds- U; x4 y: E1 e1 O' m
0 h/ g( \6 Y! }# M. ~$ @ q. B z- 6 f0 O$ P3 V& c1 H" G% T0 ^) ~3 W
- def create_text_commands(view_id):
' g" f- q1 Z! ]) C - view = sublime.View(view_id)! Y- R7 @. J8 b8 I
- cmds = []. n# c# T; n3 _) O* R L, v
- for class_ in text_command_classes:, K- `$ \! {' B! H! ^: _: d* l
- cmds.append(class_(view))3 I2 m4 O# c$ o* b" y4 i8 V
- return cmds
. d6 a) G3 d. C' W$ z* c( o3 Z - % K1 O5 ?* ?% x2 b
+ q$ |& N. C; s' g) [- def on_api_ready():
% l+ {6 Y- w3 R2 t; o1 z% e- b- ] - global api_ready
8 P" a' I X' ^" Y5 d* b) z8 H - api_ready = True
) c6 O0 E: _6 o6 p& w2 e+ t. |
1 k4 a, F; j: p: }) V- for m in list(sys.modules.values()):+ ~8 R, e Y. ^
- if "plugin_loaded" in m.__dict__:
# I/ T- R) p' a" }8 |$ q - try:
" H" i9 Y' G J) `% X# f9 ^( `! D - m.plugin_loaded(): j$ u$ `; q1 r r9 w
- except:5 n' F0 f2 j, T% i' i6 _ U
- traceback.print_exc()4 B5 Y6 v6 T! s8 E( A% q, r
- " W! }% ]: \& h, e6 C' I
- # Create ViewEventListener instances$ i" D" g) d$ c' F- @# w% p
- if len(view_event_listener_classes) > 0:
9 `4 b* v$ z7 h2 U - for w in sublime.windows():3 E0 K* x7 ~/ R) H
- for v in w.views():
$ B! T! @+ X- ]7 U* K# h" e, i: w - attach_view(v)
5 c6 B$ V2 |+ \ y - 1 n0 H9 k5 v* u$ k3 u
- # Synthesize an on_activated call( V9 \' V9 d) }
- w = sublime.active_window()* `- |& W% h; p' ~
- if w:7 ~8 S9 a0 `6 o: r! {1 L0 @, R
- view_id = sublime_api.window_active_view(w.window_id)% p6 A7 H3 @7 V0 @' L0 K& A
- if view_id != 0:7 D4 H% O. z/ ~
- try:
" _ b- w: d- w1 S6 s; n( G - on_activated(view_id)! h4 \7 V4 A [2 B# |! Z) q, _
- except:9 K I( @3 R, p6 G$ W' M
- traceback.print_exc()
! Q+ v) w' {: h. |1 ~ - 0 B c7 k. A% n$ l) W) x
- 5 N0 L* E0 k- ^$ `5 m
- def is_view_event_listener_applicable(cls, view):$ d5 x" c, S4 z/ N' s2 x$ Q _
- if not cls.is_applicable(view.settings()):5 U5 @( d( ]: ~3 X
- return False
/ A! X; e3 f3 K' C# G
' F8 Q4 {, p3 h4 }5 A% V1 S- if cls.applies_to_primary_view_only() and not view.is_primary():' F2 r, U. e- U$ _) J6 W+ c
- return False' F# M# E1 i; {5 \ L1 p" @. ^
7 Z/ J; ?. N3 ]5 a. N5 Y- return True
( o: l+ n* W' f1 q) s! F - 9 H3 q9 S, S# O4 q; T
- ' Q( G F$ z* S k' T% { _3 |9 \
- def create_view_event_listeners(classes, view):; L, `3 r! J" h" Q# x# { p( s
- if len(classes) > 0:
8 d) o3 x/ k1 c - if view.view_id not in view_event_listeners:' W. ^8 ?& C# S; b
- view_event_listeners[view.view_id] = []
* g: G4 F t' R$ t - " |+ P3 S5 s" P z' D- `" {
- for c in classes:
; U# O+ C1 X* Z - if is_view_event_listener_applicable(c, view):
( `7 H/ A( z, [& W% U0 j3 r - view_event_listeners[view.view_id].append(c(view))
& [) q8 @' e) N* ~ - % ^& j' d+ j- Y0 F
- + Y8 s* Q% q' p1 `0 v2 w: T
- def check_view_event_listeners(view):4 r( p8 w' }$ \. }* v i9 w
- if len(view_event_listener_classes) > 0:3 a( J" l7 {+ c9 e5 S+ s- f
- if view.view_id not in view_event_listeners:
! w/ F1 Q1 j0 j1 I% \ ] - view_event_listeners[view.view_id] = []
9 u1 N4 h1 _7 t8 d4 S. `
) {6 R* U% D/ u. N n* j& a- listeners = view_event_listeners[view.view_id], x% w* k q' |! f
C4 w. R6 _ e% O7 J- for cls in view_event_listener_classes:
U# ]% x* ]* p1 X( E - found = False
* J" O( ` C) D4 F- W - instance = None
, f, n( X }) R7 i7 b# x* g - for l in listeners:
9 T- e3 T& e9 ]2 N0 n# z - if l.__class__ == cls:$ K# t' e" D6 C4 {: J9 A
- found = True
* X3 A9 C! N, [/ F+ b - instance = l
+ F; Q8 ]# m4 F; u: M5 [" F - break8 z# I5 q8 h0 ^/ m/ E
$ M& E" A3 b5 K% r" z+ s( ^- want = is_view_event_listener_applicable(cls, view)+ r7 X3 f' H" }) ~! c3 T
- 4 C* K. L, q [5 s/ Y& m
- if want and not found:9 y- Q4 A: C6 y0 L8 S4 U; R, U
- listeners.append(cls(view))# ^- r4 Y; P8 ~! A- _5 c
- elif found and not want:
4 K( k4 h& e! S1 ~9 b1 w) C4 k - listeners.remove(instance)% O$ _- S+ D# b0 }
- 9 M: d* f% p- F. H0 }$ ]' o0 Q# {
* w+ N- n; c2 X5 A1 p0 q( Y- def attach_view(view):' Z/ C) s3 \0 O6 c/ B# f' L( T
- check_view_event_listeners(view)
3 [, W/ W) p$ \% j
+ Q& k" m" D8 \ C' C- view.settings().add_on_change(
$ w5 h0 k) Z0 C9 v - "check_view_event_listeners",
+ S5 K, }% K" P9 [# Q - lambda: check_view_event_listeners(view)), M: X) Q/ `# I; o2 `! X
- 4 y9 A5 S. H" K2 B0 @/ o3 l0 w# l
- 3 K$ |6 p9 K* u$ n9 P
- check_all_view_event_listeners_scheduled = False
7 T1 T" `. L$ C, Z, l, z9 A
/ I5 p/ G H* R7 e y
% }6 t+ ]7 X3 ~: X: ?2 j( m! H6 H- def check_all_view_event_listeners():, Z7 L0 w, Y: t8 d5 }1 a/ v9 s
- global check_all_view_event_listeners_scheduled
3 x) u. E5 E1 I u+ j - check_all_view_event_listeners_scheduled = False( i0 |9 c% Z! @# j( {% q& Q: P- U
- for w in sublime.windows():2 P1 j" t/ J9 H$ M
- for v in w.views():
5 U" f- I$ t/ S* K3 k; { - check_view_event_listeners(v)
# |) t$ O' T) d( k - / T ?4 c) N: g5 W" l
' P1 j# w' f; \4 C8 u- def detach_view(view):* Q! H1 W' i Z2 k. m3 t
- if view.view_id in view_event_listeners:6 M: H. n3 P# j( m. R
- del view_event_listeners[view.view_id]! j0 M1 b# f' o \8 v
- % F+ v. S4 W" P" [: H7 I3 o
- # A view has closed, which implies 'is_primary' may have changed, so see if
$ t4 M1 C- C& a# U) M - # any of the ViewEventListener classes need to be created.
1 M9 ~8 ]5 H) X" d. Y# l& c9 N+ W - # Call this in a timeout, as 'view' will still be reporting itself as a
" a* O5 U% ]' C7 F - # primary at this stage
, ^7 E2 k7 ?2 u3 a- J - global check_all_view_event_listeners_scheduled
% x# a& g4 p+ q, p! T9 L+ M$ C - if not check_all_view_event_listeners_scheduled:
8 K% w# _7 k- ~8 C - check_all_view_event_listeners_scheduled = True$ ?- k. j) }; V% P, U
- sublime.set_timeout(check_all_view_event_listeners)0 U3 v. X' X1 C& a6 j
- : v" O4 U- s8 R' ?; J
- ' [$ d' `# R/ v7 N
- def event_listeners_for_view(view):1 U4 U6 `: A4 Q" |$ M. w) S8 ^
- if view.view_id in view_event_listeners:
z+ g8 t, X9 p7 z8 j - return view_event_listeners[view.view_id]
" h& P! [9 l6 U. c" l - else:
% c5 I+ g; U; N% y( u. x' ?! X" Q - return [] N+ R$ M7 p6 f7 V+ F
- 0 s4 S6 m" N/ A7 ~0 l: z
% [9 p6 k; P+ _$ \2 J @2 \# I- def find_view_event_listener(view, cls):
/ E9 n$ t3 {" E* ] - if view.view_id in view_event_listeners:; j, ?8 X7 _- M& c+ M( y- |8 X
- for vel in view_event_listeners[view.view_id]:2 z$ j1 ?, t: U* T2 i
- if vel.__class__ == cls:) N9 ^1 X& ^3 ?2 Y# E: P. P+ u, t3 B9 Z# y
- return vel
4 I, j7 I: l) y& O - return None
& e2 o$ ? j# m3 \* o8 E - ; X- r$ ^! O" ?6 C
- 8 D$ U) G% e1 q) t6 F9 R9 U0 p, e
- def on_new(view_id):2 y% ]- d \' L9 @$ O8 u9 B
- v = sublime.View(view_id); O7 H1 r `9 k+ D) T
, i3 x( j0 D, ~7 ~3 ]; `- attach_view(v)
6 @6 \3 \4 D6 R9 f8 P1 ~2 X
+ \" e# l, A7 l* W- for callback in all_callbacks['on_new']:+ ]$ @' V# j* S+ L
- try:& t9 q( Q1 T9 o& F4 Q) p8 L8 ~
- callback.on_new(v)
. G" X3 v2 _$ d" J6 Y! O: ?5 N - except:
/ G( @) m1 w0 q# F5 ?! D( ~ - traceback.print_exc()5 z* P; g3 b4 B& u+ q" A
- 0 |- R* N1 ^, [1 f1 i9 ~
" q; \5 p1 U$ ?8 H- def on_new_async(view_id):* [! h h- |) x! U4 h( s( h
- v = sublime.View(view_id)
, B$ Q: ]. U8 z7 o, F - for callback in all_callbacks['on_new_async']:% a' K4 F8 A7 k5 t0 ^+ F
- try:4 X) O) Y0 m% m0 N9 N
- callback.on_new_async(v)9 V: {1 Y. U3 {- l2 E" x
- except:
6 q5 b( ^3 H7 o4 d% T* _ - traceback.print_exc()
% a9 m5 w" _1 A* J - ' G2 i0 Y S3 F( a! ?: C
" l A/ l; Y$ `/ g1 z- def on_clone(view_id):2 y* F/ n" |1 @' [) h S7 s
- v = sublime.View(view_id)- W7 \6 R* s( q0 w8 `- E' L
! K5 F$ C! C7 ^0 n& t' m* @- attach_view(v). e2 R3 M- h# A5 Z: {! E
- ' x9 p# N+ O% N$ B( ? d
- for callback in all_callbacks['on_clone']:4 t$ R$ q/ w& S5 y- I1 V- T$ e
- try:
5 o* K9 R' ^7 h8 J8 f - callback.on_clone(v)% b- ~" i5 X5 P- U
- except:
6 l, U# B+ b4 y+ A H2 u! P - traceback.print_exc()6 |! y' {% r, m g- h0 n* u2 I
- Z8 v6 z2 o1 A+ n' g
) I- Z5 ^% Y7 P! ]# j0 p- def on_clone_async(view_id):
7 D2 C; z8 h- b u9 d: z - v = sublime.View(view_id)
b- u+ d: T6 |+ Z# j% ~: B! k# D - for callback in all_callbacks['on_clone_async']:
! `: l7 X6 @! \ ^. U# G - try:
3 q) L: _+ K7 x5 } - callback.on_clone_async(v)
^( N; r7 Y. ^& P! x8 v3 j - except:8 X4 h- x/ I9 V+ e' n
- traceback.print_exc()0 E7 j1 w! M y0 I# W
9 ?5 t2 H* f# T$ |2 y7 \ w" p
, D- }+ E4 M* U/ R) N$ ]- L- class Summary(object):$ t+ y& n7 z9 q3 N, X3 t
- def __init__(self):
6 T6 I+ h2 b/ O/ v - self.max = 0.0
! }- a3 M! H8 k0 g. u- R - self.sum = 0.0
( M; G. ?* Q, S7 W8 y - self.count = 05 q4 B: B* q, H/ i/ K& k# D6 y
- ; P& J3 j' V V% T
- def record(self, x):
4 a" F2 Z% w8 v; L - self.count += 16 x8 O% S4 C+ s$ k% s- _
- self.sum += x
C* q+ r/ s i% N6 y - self.max = max(self.max, x)" W0 G6 f% T2 [( b# }, Q7 d
- $ H0 `9 g. s& [2 s: s+ W) [
- def __str__(self):5 [6 d% R- r H9 C3 K: f ^0 Q# P
- if self.count > 1:
4 c9 m; b U H9 i - return "{0:.3f}s total, mean: {1:.3f}s, max: {2:.3f}s".format(self.sum, self.sum / self.count, self.max)/ E$ U. ]/ X) |2 J
- elif self.count == 1:- m U7 p: `& @: C6 M9 R& ~
- return "{0:.3f}s total".format(self.sum)9 _5 t% X7 z0 m* W' e
- else:
, J, X/ L1 c8 z* ]1 e - return "0s total"0 W. m; n% r+ {
- 3 ~" E* X h: @! f
4 d! p* e9 y! n/ e* K, s& R" O z- def run_callback(event, callback, expr):# H4 e# {2 y' ~% v. [3 N' e6 ]
- t0 = time.time(): U5 @! a- T2 u+ p# S b
- 3 U& ~: O' [2 y f9 M
- try:) o* Y/ K8 O; j4 b* |. y$ `$ v& _" W
- expr()8 V) Q9 v7 H7 r1 E
- except:
. A6 @% O2 g4 f. b! ^# t - traceback.print_exc()* R, Z$ x' }& |* X" y; m, [0 i
- 1 A8 u6 @6 L4 d1 J C) s, N& V6 g
- elapsed = time.time() - t00 Y! ^& F. Y% o9 h; D
: c- m9 l: I* o. u k- if event not in profile:
- W9 \) W2 ?$ [ - profile[event] = {}
; Y, a4 `9 _0 ]
( c( B0 b9 X! z2 s! Y- E' h, A- p = profile[event]( s9 h+ @+ w e" Q4 d# n
1 o% H8 `+ A( L6 ]6 U; D, ]- name = callback.__module__( g1 c" Q9 j! i C
- if name not in p:+ M- c5 g" f6 ?9 ]
- p[name] = Summary()- d: Q* b. @4 Q7 Q3 {9 I% `
- 1 m6 X6 U3 v0 `
- p[name].record(elapsed)
# R3 R5 T* V- H8 ^" j7 s8 r - 7 I( \0 T& L1 I( T' p
3 h) H3 O& w" _9 ^- f- def run_view_listener_callback(view, name):
$ p$ u/ ]% z/ W# _2 {6 d6 }7 z - for vel in event_listeners_for_view(view):
: O) I& Z$ t2 Y: h$ y - if name in vel.__class__.__dict__:. J0 |. I; b W2 `+ M" K
- run_callback(name, vel, lambda: vel.__class__.__dict__[name](vel))8 k( K& v: `0 I! n1 r
- 0 t1 R1 n% B/ P8 ]
- 6 r7 M5 C; P! x& o# m j5 @! i
- def run_async_view_listener_callback(view, name):/ i! y7 I5 S Y: i/ H) I, p8 |
- for vel in event_listeners_for_view(view):, x& I c# J. S! b3 N
- if name in vel.__class__.__dict__:
0 e- `0 v- g3 S# c5 M& S) g - try:
0 h% F6 r' M6 H6 \ - vel.__class__.__dict__[name](vel)4 O$ r2 r' `* v+ h
- except:
9 ~" a5 ?( L Y N0 F: z) a( c B) ^ - traceback.print_exc()1 a5 R% ~8 X$ O# @4 e2 j$ i
- 3 W8 A6 n* {! t# z9 X+ F
- 6 U3 f4 r) d3 A
- def on_load(view_id):
7 b8 U: s8 N& y* Z; L - v = sublime.View(view_id)5 X3 H8 e3 F+ Z: a T* W6 I4 i
- 0 X8 a3 K& L. i% o- ?! ?( h
- attach_view(v)" D1 c X3 a) X$ n
- " D& i1 {$ }* J9 k4 n+ k3 O H
- for callback in all_callbacks['on_load']:
8 e( w6 s$ a& T' c - run_callback('on_load', callback, lambda: callback.on_load(v))
8 l# n% N+ X ~+ n0 F8 B+ t - run_view_listener_callback(v, 'on_load'): L* l/ x4 R! o
8 e+ C% L! s! S1 g- c
+ ?" R( z6 j; E: @5 X- def on_load_async(view_id):
. [" l+ G; Q$ l9 t! V - v = sublime.View(view_id)# N$ X; Y( A+ z5 o0 S3 ^
- for callback in all_callbacks['on_load_async']:
' I- ?" w: H! O2 c! z& R - try:
5 k( h+ V7 @" b+ V N - callback.on_load_async(v)/ H L+ i+ Y# J! h; x
- except:
( n9 Z/ o$ H( T. C# Y- b, O - traceback.print_exc()
' _1 ?* Q, g4 F - run_async_view_listener_callback(v, 'on_load_async'). h5 t% n9 t) u0 k
- . ]* L9 `1 i w7 j9 r0 l
- / O4 ?8 f6 `. q6 f! Q! `
- def on_pre_close(view_id):
2 F8 P& L. T' |! R - v = sublime.View(view_id)
i/ k. g# Y# g$ n( N - for callback in all_callbacks['on_pre_close']:( l) h. @6 ]4 ]
- run_callback('on_pre_close', callback, lambda: callback.on_pre_close(v))( S- d# A+ R ]- J. \2 H' V7 m
- run_view_listener_callback(v, 'on_pre_close'), {: \8 `& R" t: G( ]; F( J
+ \5 C$ b7 F, D9 T! a
, j, M3 d2 M N. q# X- def on_close(view_id):
8 J2 `2 }; x0 I: b) M: V - v = sublime.View(view_id)
1 h d5 `& l( Y ~0 N
; C: m" d5 A- z5 _# j4 l- run_view_listener_callback(v, 'on_close')" l( b5 v2 Y$ Z ^: }$ d
- detach_view(v)
0 }2 c( Q1 v/ B3 ^# K: X - # V- G) k4 c! x; ?0 O, D
- for callback in all_callbacks['on_close']:
5 K: C7 ?# l4 d( `( k8 p - run_callback('on_close', callback, lambda: callback.on_close(v))9 X2 H( R* J& c8 ~
! @1 @8 s" G+ g8 j: R# y
( e0 j' S( T$ W7 t L4 u- def on_pre_save(view_id):+ J, b \# |: T. k
- v = sublime.View(view_id)
& h3 h8 K( }" `, g+ [( f0 c& } - for callback in all_callbacks['on_pre_save']:( N4 V& R l: p) t# w( e3 n
- run_callback('on_pre_save', callback, lambda: callback.on_pre_save(v))
5 w( S& S9 b4 f - run_view_listener_callback(v, 'on_pre_save')
J7 c5 d, G& t8 L
. `, H* d( w0 J- , b a7 N) o8 J' V
- def on_pre_save_async(view_id):
( C$ t# @% M' V% P - v = sublime.View(view_id)
/ h) u4 }2 [! U' X6 k4 w; u; b - for callback in all_callbacks['on_pre_save_async']:2 Z8 y q- S7 M& j4 T
- try:
5 L# L+ J6 Y5 c. l% \5 E& y - callback.on_pre_save_async(v)7 h- H$ x% [: F6 g( @& h
- except:
0 P4 T l6 w t) Q1 H5 ]( m8 ?5 u - traceback.print_exc()
8 P: {) K1 A. x: l7 r& a6 U - run_async_view_listener_callback(v, 'on_pre_save_async')
- A& o3 J# J' N( f' a+ w& p
$ B1 {! i3 n: f' ^
5 Z1 }0 {3 t+ \# s2 S$ @2 K0 n8 |, a- def on_post_save(view_id):0 b8 q2 ^# L- w, i$ j
- v = sublime.View(view_id)
7 L, z/ [. m& M - for callback in all_callbacks['on_post_save']:
4 ?* j. a: p1 T8 ]/ S - run_callback('on_post_save', callback, lambda: callback.on_post_save(v))! l- M' w9 u: V) J3 j+ b3 u
- run_view_listener_callback(v, 'on_post_save')
! Z% }6 X0 Y# o, p" k
2 {6 @0 q; B J- N8 i, ~, s4 T- 8 [* K* t- S! p1 c& m- Y
- def on_post_save_async(view_id):
8 r7 _3 O- A. i* w - v = sublime.View(view_id)9 I, K" e) y8 ^6 U2 W
- for callback in all_callbacks['on_post_save_async']:5 J( ?3 @4 P& J8 O# f1 l! m5 H
- try:" C4 o! G! z: h0 c
- callback.on_post_save_async(v)
9 Z0 g- Q. e" v% u - except:# j% I# {( |7 d' I3 S" J5 C1 e! {& O! W
- traceback.print_exc()% B5 a9 {, f# V S N" u' Y
- run_async_view_listener_callback(v, 'on_post_save_async')1 {% T$ X9 R1 f/ w4 W7 U+ n
- - [7 y; r9 V* p, |; [' y5 C
! H. Y/ B7 R: |* X& |5 A- def on_modified(view_id):2 t1 h; g5 C, a0 F0 Q$ q2 C
- v = sublime.View(view_id)
* y0 u4 z. |. V8 I3 V' `& w; D4 w' Q - for callback in all_callbacks['on_modified']:3 K$ N9 {6 t# W' c; {
- run_callback('on_modified', callback, lambda: callback.on_modified(v))( }! N3 R( T) n- w
- run_view_listener_callback(v, 'on_modified')+ k7 |4 j: M: O1 w
! O M* Q8 N- o+ ^- Z1 J' V8 G3 _5 X: \, g
- def on_modified_async(view_id):
7 K3 J) B! R, m6 q: [" { - v = sublime.View(view_id)
- @" ?% { k3 i' k, l% u. U' w) C - for callback in all_callbacks['on_modified_async']:
' R- f W2 _8 Q - try:
6 |+ t( L' \$ _3 ~ - callback.on_modified_async(v)
& O# B0 [, D# G1 M - except:3 m+ {1 v; ~- ^' f
- traceback.print_exc()
7 L6 ~: L8 ~1 O; n+ W. T8 ^% h - run_async_view_listener_callback(v, 'on_modified_async'), P1 q0 U& T% H
- ' ^& O- @: H- h, g2 |8 |
- " S( \" W' w8 p" ]% l
- def on_selection_modified(view_id):
, O/ Z [+ p# \5 E. t" J$ i7 U - v = sublime.View(view_id) T5 }' t- c/ v
- for callback in all_callbacks['on_selection_modified']:. G" ^4 I+ F8 |7 U: U6 A8 @ p. n
- run_callback('on_selection_modified', callback, lambda: callback.on_selection_modified(v))3 c- |. W* V, u& W! b
- run_view_listener_callback(v, 'on_selection_modified')
% ?" e- e8 x9 p - 8 T- [. G8 S# f- S K) c- z
: w: A; K6 n5 q- }, Y" B0 E- def on_selection_modified_async(view_id):8 w- J S4 A, y$ ^, K
- v = sublime.View(view_id)
% k3 r- O/ i1 p# [5 _/ ~ - for callback in all_callbacks['on_selection_modified_async']:
4 E7 a! ]$ y( i5 |6 l1 D - try:
5 `6 L4 J& a A, T - callback.on_selection_modified_async(v)
8 }# w" F% m/ F9 d, i0 a! N8 s - except:
- t; K0 H" L9 I. c7 H* ?) t7 J9 B) m - traceback.print_exc()
/ \% `. B0 U) K4 v6 l$ s - run_async_view_listener_callback(v, 'on_selection_modified_async')1 d6 N- u7 S% ]2 W; c, U
& G) j' J. Z# k# H3 t- / |8 [5 u$ G3 D# {# {
- def on_activated(view_id):( V8 ~2 t0 _' K$ o' r9 z6 \
- v = sublime.View(view_id); G$ O9 R4 i$ K+ U! w4 i
- for callback in all_callbacks['on_activated']:& F' s% h9 ?" J7 s* w
- run_callback('on_activated', callback, lambda: callback.on_activated(v))/ K# `( h+ J! R# Z
- run_view_listener_callback(v, 'on_activated')/ J; n; L# x1 e2 M9 [* J/ C4 C
* O+ u" b$ I2 S4 G- 6 T0 I4 ~6 P0 z/ [
- def on_activated_async(view_id):* e& \* u+ U1 t" _% F8 O
- v = sublime.View(view_id)0 s* J' V) I: ?" {) b
- for callback in all_callbacks['on_activated_async']:2 x7 V$ h+ h6 a; U+ I O
- try:
, _' v2 ~$ T% w, U, u, m - callback.on_activated_async(v)5 f$ j! W7 F/ |/ _
- except:
" W) |7 D/ o2 L' h* N+ a - traceback.print_exc()
6 ~; K. E# E8 Q4 z3 y - run_async_view_listener_callback(v, 'on_activated_async')
6 F" [- M' K/ g" a' Y" b - 5 L) A% e' l' \7 Y! a" F
- ; W j( n$ g9 y
- def on_deactivated(view_id):& b! Z( n+ `% j+ j5 E( f6 Y' A) U
- v = sublime.View(view_id)6 S; n. v4 ]' M
- for callback in all_callbacks['on_deactivated']:7 I( \/ I) I2 u
- run_callback('on_deactivated', callback, lambda: callback.on_deactivated(v))
" U# s9 X, \( ]6 @/ D - run_view_listener_callback(v, 'on_deactivated')
, E- ?$ _/ t4 \# d6 F2 | - , s1 Q. P% Q2 w8 ~
- * f. H# b" S- E
- def on_deactivated_async(view_id):# `7 P# e6 y: g7 y2 i
- v = sublime.View(view_id)! A) B0 l& J [: ]# g" r
- for callback in all_callbacks['on_deactivated_async']:1 d( v4 g; D4 ^1 E u3 s! O8 e, ^7 j
- try:
_( I7 f4 K' \" Z5 w8 { - callback.on_deactivated_async(v)& y+ Q) h0 s' F7 t, ]& W
- except:
5 _9 K9 M, W) C% s - traceback.print_exc()
( q5 `* k: N. v% L# U, a- F+ p - run_async_view_listener_callback(v, 'on_deactivated_async')
- c+ Z, W! F; ?3 M7 i - + R' Y0 R0 H0 O* G
5 Z0 f# E5 `5 G- def on_query_context(view_id, key, operator, operand, match_all):
8 E5 }& d' X# ?2 b: G3 E - v = sublime.View(view_id)" ?+ y0 h& E& @. B
- for callback in all_callbacks['on_query_context']:
& X2 v; x4 y. H1 i6 c - try:: E E+ l5 A0 _0 o, D6 H- F
- val = callback.on_query_context(v, key, operator, operand, match_all)
. e5 b. f& v$ {) O' @" h; ~. R/ b7 ` - if val:
/ V4 s% H& C( G( \7 t' J4 h - return True' E; K! ?* k! q. f% a
- except:
6 P7 d {' r% Y; L- e - traceback.print_exc()
$ J' f" j6 m& @/ x/ D& m - : Z# }% ~4 @" x$ r+ b/ j( Z
- for vel in event_listeners_for_view(v):
" O5 Q( e* X6 v/ i8 z1 t - if 'on_query_context' in vel.__class__.__dict__:: F: j5 j' C8 g* z0 W+ k4 D3 U
- try:
0 b* x9 b2 x- U1 D% f8 o - val = vel.on_query_context(key, operator, operand, match_all), N& S. U% ^7 E6 P
- if val:3 e2 g' v* w, s% s$ ]/ F
- return True' G7 n# F4 u0 r: h# k- {) _% n+ E
- except:
& B4 {( b7 l! b/ n' W6 v. n - traceback.print_exc()
& J0 n2 A1 F% c$ j- ]; y
; `& G/ o0 s' q5 y5 a$ V6 p' G- return False. ?" M+ G& [! b* |5 t4 p
- 0 T4 q/ i3 O* h9 O0 T0 c
! D4 ], a) }- Q4 ~/ a. X- def normalise_completion(c):! d$ A) f y2 I! ]
- if len(c) == 1:
8 F `0 ?* t. n- r3 b/ g0 d- I - return (c[0], "", "")
+ \* z+ ?; @# P# Y' n M7 S% T2 g - elif len(c) == 2:
8 r: e, n0 a* A, h5 T - return (c[0], "", c[1])
* }: V5 B( [" Y Q d1 c - else:, b& J, x; n1 D$ F' H8 r0 Z. l
- return c
' K4 c% P6 Y( R( V
' c2 z4 N# g, s# Z" }' T
& {. v. \. [5 h3 P- def on_query_completions(view_id, prefix, locations):7 Z# Y# \9 j: G" d
- v = sublime.View(view_id)
6 |9 H1 k5 o) f, F7 z' a3 k1 d - 4 \5 Q# o S& _& B3 {* S, p3 F
- completions = [] z) U0 g+ x) K* m# g( |
- flags = 01 \# @) w6 h) w' C5 c! _6 x9 t1 c
- for callback in all_callbacks['on_query_completions']:& o- q: |, n, W, k B; Q4 h' q
- try:* L' Q [: b8 I; o
- res = callback.on_query_completions(v, prefix, locations)
# X. \2 J* D, z9 O8 [% d/ D; o1 M - 3 r: b& M* h3 l2 g6 V
- if isinstance(res, tuple):
* ?8 t* U4 a) Z, U2 m! v - completions += [normalise_completion(c) for c in res[0]]+ H# E" K1 d8 ?) }0 w
- flags |= res[1]
- V9 N N" b: Q8 k! g) \) Y - elif isinstance(res, list):3 }) ^* e( q7 j& e5 c; g9 S6 c3 `
- completions += [normalise_completion(c) for c in res]# _7 R8 E, G- n1 A
- except:% `9 R3 e2 O. ^# T0 I
- traceback.print_exc()7 r1 E" M' R5 c6 ?. {$ t
- 9 ?0 Z! J8 H& [: s. R
- for vel in event_listeners_for_view(v):
' O g- t# r8 d- H2 x1 U - if 'on_query_completions' in vel.__class__.__dict__:
# K3 X+ k# b, V% q+ J" E! x$ N - try:
7 c* d& _% u( ~& ]5 ~7 x - res = vel.on_query_completions(prefix, locations)' p; i. D, Q: A! ?* u
: }) B- O6 z% X6 W+ m- if isinstance(res, tuple):7 I. T+ ~2 d7 S6 O6 O' r1 c
- completions += [normalise_completion(c) for c in res[0]]
+ Q7 u- d7 M2 R8 S, r2 R1 l: p- I - flags |= res[1]
# A4 T0 u+ d1 S# m! Q - elif isinstance(res, list):
9 p5 S# r3 J' _/ b& x7 H& y - completions += [normalise_completion(c) for c in res]- a) y: b% k7 Z1 @& K2 ^" z) A
- except:
$ N7 O) }. s7 b* N - traceback.print_exc()
6 \$ t* F# ^ z ?
0 b4 \/ ^" k9 u/ t- return (completions, flags)- M; q2 v" Q+ W, F4 q- [& O
- ! C3 g0 a) W$ |/ M
- 8 {8 }6 g6 Y7 i o% F
- def on_hover(view_id, point, hover_zone):" l+ d* { [2 L: |
- v = sublime.View(view_id)+ O& t4 x8 Y' d5 D" j! p
- for callback in all_callbacks['on_hover']:
/ z( t d! ~* ?: D% C9 T8 y+ m5 Q - run_callback('on_hover', callback, lambda: callback.on_hover(v, point, hover_zone))
; Z) I; _; Z! e( N - ) Q/ p/ S0 c# [0 W, s+ P7 B
- for vel in event_listeners_for_view(v):
9 N. n5 y2 w6 Y" w+ ? - if 'on_hover' in vel.__class__.__dict__:0 x* [! N% a% F( ^
- try: j$ m7 N" V6 H- {. Q
- vel.on_hover(point, hover_zone)0 z* s9 E8 q9 x/ y6 j( a
- except:
" |+ ?( Z& x" I% o0 L: H" L$ T - traceback.print_exc() C( T* H7 {* M$ J+ s$ v
- * T' x/ w% C5 L* u
! ?$ g; P$ ^5 p# x* t7 M- def on_text_command(view_id, name, args):3 m$ ^! x) m+ h! c; M) T7 k5 _
- v = sublime.View(view_id)
! w2 ?& }. {! S& J
, y! R& h& \0 b: r% b- for vel in event_listeners_for_view(v):
. l/ C8 A6 q0 C) N$ c - if 'on_text_command' in vel.__class__.__dict__:
/ G% E; y2 D7 p - try:
; r+ [$ r R/ W) p: S8 b - res = vel.on_text_command(name, args)7 H& u* P* [1 ~: o
- if isinstance(res, tuple):
! f- V' s0 h$ ?% B( A$ x9 W/ \ - return res( X7 E4 Z! b, d3 Y
- elif res: {( V" U) H& W( Z- g( R/ D; l: ~# e
- return (res, None)
0 C- F, @; [6 A* m2 s - except:% z, w- R1 z3 P+ \7 ~
- traceback.print_exc()
% J. H- W0 t- R0 ~
$ q/ j/ w% {+ G& N- for callback in all_callbacks['on_text_command']:! h$ {+ T; t. k1 ?6 q
- try:" _- P' P/ U! L! L* }" \( S
- res = callback.on_text_command(v, name, args)
# d6 {0 x1 f) Y5 a; E$ X* } - if isinstance(res, tuple):0 W1 K( z4 Y2 j ], M$ n( {
- return res, x! t% v9 p9 ]
- elif res:
# F- g* z* e; X L8 z - return (res, None)
! V% D6 g3 j a9 Y$ M% v6 Y - except:7 U, t/ h. P7 z* M5 _/ D
- traceback.print_exc()7 s2 a0 ^* D% C9 g* {1 p5 N
; ?2 N' g: E1 c9 \; O# H2 {2 Q- return ("", None) m! U: i; C3 [+ Y+ T' X
- / @$ {9 ]1 }& V$ }" c0 n+ r
5 i7 F1 O2 r; [: I6 e5 V" d- def on_window_command(window_id, name, args):
" ?. I: i1 B/ W( b- o |# L - window = sublime.Window(window_id)! N, e1 b" E3 E0 A% K
- for callback in all_callbacks['on_window_command']:! i- {4 K& x/ D! ~/ B4 g
- try:
, _7 h$ h3 b# L - res = callback.on_window_command(window, name, args)
- n3 E) |* a/ r( G, j - if isinstance(res, tuple):0 h7 p6 ?* r/ a) y! u L, K
- return res4 B. }6 m' ]' `2 B; o# S+ {3 o# j
- elif res:
( ^) B, \9 \ M ] - return (res, None)
3 B" d# D" L. U: R1 X, t& l - except:6 r4 D0 w4 L/ @
- traceback.print_exc()
% c) }/ M& W& R0 I* {; m; f - ! ~; G1 Q$ h+ ~/ q0 r3 @3 q; N
- return ("", None)
' [' q1 P/ P) _! {7 S7 ? - 3 A1 N6 Y* Z: i; J( l' R
* r0 k; Y- e, P- def on_post_text_command(view_id, name, args):
3 ?: H% Y) o; { v - v = sublime.View(view_id)& ^ [8 \- j. I5 x8 g3 q' c
- for callback in all_callbacks['on_post_text_command']:$ a3 b, G2 W3 E# I W) v9 _$ |! e$ x
- try:
- O6 [# O( V# g) L3 a - callback.on_post_text_command(v, name, args)
' I4 j7 m8 X5 f6 y# R0 Q V9 n, e - except:
9 B+ ]1 p g. c+ i( ^$ }) h - traceback.print_exc()$ E0 W3 ]& C% q7 O( S; ^, K1 V. g
$ ^; Y ?7 A* {% s2 l, C- for vel in event_listeners_for_view(v):
" A3 g' ]) H% ` w - if 'on_post_text_command' in vel.__class__.__dict__:
) e# X3 b9 ~. U6 W - try:2 l; H1 Y, d$ P u0 h- i
- vel.on_post_text_command(name, args)3 C- p: Y5 I( I
- except:
( O [6 R' v" @3 [ - traceback.print_exc()- J# I( P( e o* m+ h* \
- X: |8 E1 v3 u' Y
- , B# W; \% }9 l) ~/ ` o
- def on_post_window_command(window_id, name, args):
; u7 e: H; [$ o0 H4 ~# S - window = sublime.Window(window_id)
, a8 F* x" Q: w- U - for callback in all_callbacks['on_post_window_command']:
2 @% @& u* l6 s - try:
. W% }- s# f& b. S. @ - callback.on_post_window_command(window, name, args)
1 l' e3 s# Y" i4 E) | - except:, i* l& M) N- c0 |2 R: M3 Z
- traceback.print_exc() T) e$ S& K) ]8 a* ?* s- _
- $ Q! f) q/ a8 s+ w w' z/ _- N
* F3 Y+ H+ o9 k, m; H- class CommandInputHandler(object):# c: t9 B: f5 d% N5 X: k
- def name(self):
* B8 l' F7 H6 c2 H - clsname = self.__class__.__name__) a6 Q) Q. { k; U
- name = clsname[0].lower()# U$ E7 y5 d* A4 L& l
- last_upper = False
& W3 j) c4 k9 H8 k: B, y - for c in clsname[1:]:
) t& z7 m+ n9 [2 i+ X& L - if c.isupper() and not last_upper:, Y7 y! W2 t7 F6 ]" i1 T
- name += '_'
2 ^6 ]. Q2 k1 n, W( x' O% N - name += c.lower()
8 T: q; E; m% k! T0 d" S- F - else:
+ K* X$ `. ^& e: v8 x - name += c
% P+ \+ n h( ?& N" h% o2 a4 S - last_upper = c.isupper(); J* p0 g$ P" e/ ~9 j# R7 P
- if name.endswith("_input_handler"):
) h+ l5 h) C& g2 v \ - name = name[0:-14]) w# f9 r3 t. p# A- r- d
- return name
. ] _3 g8 W7 d- k& ` - ! W* O! `8 D8 ~1 g1 `$ }% w' ~2 C; W$ q
- def next_input(self, args):2 x$ s2 ~- v% e3 F3 r
- return None0 `' j+ t% j; ^) h) Z
, |' p4 E& {8 n. U- def placeholder(self):
9 j1 t! Z& t+ w8 I! a - return ""
. R5 x0 Q/ S/ \6 B) b7 b7 A - ) p$ y j7 e) ?( C, S% O) ~3 i* E
- def initial_text(self):
" ^" K r9 g+ v - return ""
; o+ ]0 B6 Y+ q# [. c! F - ; k/ ^9 `& ~7 l) b2 J7 o i' j
- def preview(self, arg):
7 B S0 h: B5 y - return ""2 @5 A; r: w. Z! {* G) I
2 E0 W" {0 v) W8 J8 x3 b x- def validate(self, arg):/ t0 \: |! z3 G4 J' t: q; I
- return True2 g z( ~( {8 v) l/ T% y. ~1 O* x7 ]
- 7 U# x* p& C% m! f( }- @
- def cancel(self): z, l# h# M$ w- L, x
- pass+ q: `( ~" c2 d
$ V4 T* l* X5 ~3 W" Y& A- def confirm(self, arg):
) O& m. `2 k4 ~2 D e. S - pass* N2 a V. d- m, U
8 R) R: b. o5 j. D- def create_input_handler_(self, args):
0 D* ]( R$ K( M8 y1 o2 T; n1 k# M - return self.next_input(args): L! Z' B n8 k* |
1 u/ L9 w6 j, V- def preview_(self, v):
1 q% L1 o2 g- b& F9 ~ - ret = self.preview(v)
1 `6 U6 H! |8 y0 h. g p2 r* ~ - - O" N5 Z. n# [
- if ret is None:
4 [1 H$ Q' a3 x$ z2 d* l - return ("", 0) R: M7 X8 K" W f! {
- elif isinstance(ret, sublime.Html):+ ]& }$ ]8 E9 V' \7 Y
- return (ret.data, 1)% R% ?! {+ a* v/ w9 j! U3 e- l
- else:
; ^' {( |# W8 w- j& ~$ ~ - return (ret, 0), Y k- j" b' Z* a) V5 O1 p: m
% u3 d, i8 N3 w8 d" Z& T- def validate_(self, v):
5 W Y6 a$ K5 ^2 h3 Z+ ~- k - return self.validate(v)
2 J4 L7 K3 k8 l
1 R4 s# ^8 v+ T' c- def cancel_(self):
/ `/ p5 a+ C4 B9 |; H( s - self.cancel()2 q: N5 U' {3 G& S& L4 A
- ; M/ J; q# B6 K+ `9 l% c) _
- def confirm_(self, v):# B; ?2 n6 _ P6 d
- self.confirm(v)
; \$ f3 }9 ?2 }2 i
6 N3 S3 H! n9 n3 f+ \7 K% g1 H- 5 S! e* u7 X5 t" U: @7 C0 O7 D" B' I
- class BackInputHandler(CommandInputHandler):, |6 J* L; e7 w: f
- def name(self):9 A% v* X' Q( P- ]+ J K
- return "_Back"
, ~4 K" A9 _7 W7 m - - K5 H' P# o# H- q
- ) s; n3 }9 s9 Q G4 r/ ]3 ?
- class TextInputHandler(CommandInputHandler):
$ D; | {2 e) q% s+ N \ - def description(self, text):7 z" k+ w+ ^5 n; ]! x( p
- return text8 I1 x8 X, d X4 i' x
- - _, }# p* v* f' n- w# s5 f
- def setup_(self, args):
' P) m/ a" J. e - props = {
* w' o6 k2 x5 l6 l9 @5 M& E/ U - "initial_text": self.initial_text(),& X. B2 I$ K4 E- F
- "placeholder_text": self.placeholder(),
4 t) Z5 S+ N- a, N9 {2 E( @ - "type": "text",& x$ L% j r5 j. ?( U
- }! `) t5 n c0 `
& p" v4 ?5 j% h& O% Z- return ([], props)0 d: x8 I; o/ `
- - ], u% F }5 w1 G& N0 C$ F
- def description_(self, v, text):9 m9 A; }6 S- J
- return self.description(text)2 u+ ^. W' |: D9 a! E+ f
- 8 R, c& ^6 N. J0 T
8 R' I% z9 G7 g- class ListInputHandler(CommandInputHandler):
0 h2 X: j! T( |2 W+ ^. l. { - def list_items(self):
! ^7 Y* }$ ^8 H - return []
( Z4 d+ e3 d9 q; @7 {1 j
8 n( Y) p; y! W- def description(self, v, text):
+ e9 A2 k* L2 Z. z+ g9 j4 S7 O, J - return text
* I' |0 J% L+ E3 R. R4 J5 h) b0 C4 Y
8 I; I+ h7 T% y! X2 J a/ _0 z- def setup_(self, args):
% U2 S$ X4 W! M) q N. ^ - items = self.list_items()- K$ R. @. }3 d* \) J
# S2 T2 E3 P( J5 @- selected_item_index = -1
+ }4 x( C/ ~# t: A
2 J7 P. g% I# ^- if isinstance(items, tuple):+ K+ Q/ A5 s- ~5 p
- items, selected_item_index = items8 @3 E7 i& ] Q: _( A$ Z2 J& z
- # [7 ]3 e, I; G" ]1 Y1 F
- for i in range(len(items)):
2 e" c: O8 o% a: l( ^' }; R1 e - it = items[i]
) h/ q/ [+ X7 i! y; C8 f - if isinstance(it, str):* [- w, c7 a7 d3 D
- items[i] = (it, it)
. k7 ]4 W; H! ] Q' y5 D
- V, O9 @8 b+ z/ ~3 [# S9 P& _2 t! R- props = {
( M5 e2 i" ]1 V# _ - "initial_text": self.initial_text(),9 z" C0 {' q1 B( z7 }
- "placeholder_text": self.placeholder(),- D' l; D# U3 }8 M. ^0 G1 `
- "selected": selected_item_index,
u- }2 A. `0 [$ ^* l/ n - "type": "list",
( n) a. O o5 {/ s, Z% \# ?! l - }
, A0 v7 k, L# \2 ^ - + @. j+ ?: H- \; ]9 a% T6 z$ u
- return (items, props)! u7 r8 S$ v3 c
- 9 r% ^, \5 z+ ~8 |" O- [
- def description_(self, v, text):) g, k2 z, |1 z' \1 G& o
- return self.description(v, text)
, f' |5 f. v% B& ? - ) j9 U$ O/ W, a7 H
6 r2 W' T2 k( n6 y5 O- class Command(object):
7 j' h' C" A+ f. r" I7 | - def name(self):
0 p. p# {: ^' q9 i1 x7 T$ L - clsname = self.__class__.__name__2 l& r; ]& G# [; r: K, N- c
- name = clsname[0].lower()
, P! \- z7 T5 t! |6 a - last_upper = False" l- v( A/ H. H$ Z2 p1 \ `3 N
- for c in clsname[1:]:% r( F' r( }/ ]* s/ }
- if c.isupper() and not last_upper:
( {' D9 p, p$ ]% d' y, O- v - name += '_'$ k0 V$ b7 \) {7 ]- K
- name += c.lower()9 n: {( L* T* s7 |
- else:2 j. H9 n( g, }% \& K5 @) m
- name += c
4 Z7 |7 G2 X& L, K* _ - last_upper = c.isupper()
4 I# U( V5 @* s% J8 B# A - if name.endswith("_command"):
1 V+ e% K B9 Q' U: [ - name = name[0:-8]
* G7 X; |" G% G4 O# u8 o - return name7 n! y6 ?( \7 M9 I/ x) M) a
- + R3 E j6 m) S# D/ x7 ]& M
- def is_enabled_(self, args):
9 x" d0 `. m4 I2 t3 F, B4 x6 Q - ret = None
8 i6 d+ y d7 P( ?/ ~ - try: G: K6 P" B; G) j3 q
- args = self.filter_args(args)! X2 V! T$ E4 t& C: ]
- if args:
3 f$ @( N& I' V* I - ret = self.is_enabled(**args): H9 W9 _0 {/ o5 X+ y9 u& G+ b
- else:
" |$ @9 I6 y, V6 @- ]2 w - ret = self.is_enabled(): `) I; I( Y v
- except TypeError:) L7 i0 I; m9 E5 i0 S9 Z
- ret = self.is_enabled() S3 i) H6 d; t- s8 M
- & t5 y0 q# Y, F- g: m- d6 X8 [! f
- if not isinstance(ret, bool):
$ ?& q' G' V9 q! p7 a - raise ValueError("is_enabled must return a bool", self)
; |1 I& i6 S% y- M+ P
, F4 a- R& ^& T5 t H% V- return ret
5 b9 K9 \) J. z* y+ _. h: Z
$ A3 x( g/ O% I( ?$ O5 ~, J- def is_enabled(self):- A2 i% V* A4 j: Z8 j; t. R- B2 k8 X
- return True) ^9 i. ^" ?0 ~! c& ]
# c N3 }$ }$ ?: O- def is_visible_(self, args):
! O4 q& X5 }' H5 h( _! s - ret = None
" E5 `# a. F" z$ @( G9 _! T! g/ a - try:" D" K; a3 \4 Y3 P
- args = self.filter_args(args)5 a t5 h, n0 M* ]) ~2 g
- if args:+ ?& c4 A4 u6 ~- e9 X* h8 w
- ret = self.is_visible(**args)* O5 ?+ B1 ?( E3 Q
- else:; x7 x4 p) [$ \
- ret = self.is_visible()9 k# n; w: a7 P) \
- except TypeError:
' b% w$ P. u, ~% R7 s1 ^2 S! _ - ret = self.is_visible()
. T7 z/ `3 Z. N) v - 4 |) z1 k! K' }* J4 a& r
- if not isinstance(ret, bool):
) M# V f, O% u: C4 |( m5 ? - raise ValueError("is_visible must return a bool", self)* a: s: J% Q* |' R8 b4 d* Q+ F
- . y7 f6 A; C; c7 ]
- return ret
/ v% N K! [9 b0 ?" G0 Y
1 H) ^7 O2 j- q9 p6 p/ n6 u- def is_visible(self):$ u2 ^ X* A+ Y8 x
- return True
# n% D9 C( I* O" n$ a/ P
% w# }/ ]/ s0 v L- U" T# o* r4 Y4 ]- def is_checked_(self, args):8 b% F4 h! E- T5 N" v" G
- ret = None$ s" L0 q# J# d/ g2 T. D' L) _
- try:
' t% y2 G' d! k) m - args = self.filter_args(args)
8 S+ l) z2 K6 L8 L! ]6 k - if args:
& w P9 H0 g |# g# K& E9 [" C7 m - ret = self.is_checked(**args)& C8 @8 U I. l, r
- else:
6 |! g! O! V% A - ret = self.is_checked()& w8 o/ ?6 ]6 `/ r) L
- except TypeError:) B& I9 S0 y3 X0 S5 b
- ret = self.is_checked()* T2 f* k2 T Z3 c6 E
, R% }$ [# K: s0 z8 D, ?! }- if not isinstance(ret, bool):
% ?8 V: ^5 G. j - raise ValueError("is_checked must return a bool", self)4 L+ a5 Y8 X% ` P) x5 G# @; K
2 E" I* j; A4 k) s% a2 x- return ret
& z `* D5 Q' D, F1 f - 4 x p3 Y. u& ~6 r
- def is_checked(self):
8 P7 \, s9 a& P5 @0 {9 j - return False
: O! ^% v; ~5 }# k' ]- b+ F
/ }* T! w, `( o) `# D- def description_(self, args):
8 {. R5 I4 j0 ?5 W - try:- \* k% q& Y: C# |# V; l5 T
- args = self.filter_args(args)& T6 ^$ ` z! N+ i9 N( c0 V; }1 Q! T
- if args is not None:
# y5 ?6 T4 |3 I - return self.description(**args)6 Q0 @0 _6 y* l) M! u8 A# ~
- else:
+ X1 G4 \9 _5 f# f5 Y - return self.description()' A% j) N& \, m$ r' L
- except TypeError:* z9 N. z6 v2 X
- return ""
3 c5 N5 W' v0 t! A# k0 C1 ` - 7 f: S* D. q. l- `, O5 {0 J' r7 t
- def description(self):
2 C: u' [/ p2 i- z! r - return ""
' A. s" @; g* [* s: q$ _
0 h; Z% W" `+ J2 j) D- def filter_args(self, args):
; Q+ ?, I0 N* L - if args:
' t o/ O% Z: f6 @3 [ - if 'event' in args and not self.want_event():
3 @$ z& Q5 N9 H+ n+ `- \8 Z - args = args.copy()
0 ?' u* H9 E9 X& I* ] - del args['event']! h/ b, q3 q9 x2 e
- ! H7 q/ q& ?/ [, x3 Q
- return args0 H+ H, j- @8 a$ S" i1 z
- ) q! A7 V" u' }/ [
- def want_event(self):: A4 S5 q5 J. Y) D \0 c
- return False
2 ~& }$ z! o! U( ]/ R
9 R2 j- J1 M( ?3 c- def input(self, args):
2 j3 ^- d9 O: V5 o% }! r - return None
8 }: P0 ?% G/ c N0 o& v: c
7 M6 x9 z4 w h- def input_description(self):
! E9 r6 g' y( ~' d" h5 d4 c! _$ M+ O4 A - return ""; Z; o- V; E) K* k( q. e
# B/ f! |9 w8 H( `1 P6 L; Y) J- def create_input_handler_(self, args):+ w1 C7 T0 j" t0 l+ z5 B
- return self.input(args)
& k' {- l& H/ x% u% b
' C3 F- d6 g; t! a) W( G7 G- , d |/ E& [$ q
- class ApplicationCommand(Command):% t# l3 ]& N E2 m- T i ]
- def run_(self, edit_token, args):) o" Y- ]( i& k
- args = self.filter_args(args)
) p7 A7 |( t8 t, R% d) y9 V. m% m - try:
5 f6 X' Z" D( M) R: S- ^9 w& C) _' s - if args:1 }$ A( Y w. D$ r
- return self.run(**args)
% a/ n* G3 D) L2 S+ W+ W - else:7 u- o) a- J0 U/ p7 ~
- return self.run()
, x5 Q. E: | f& S/ X - except (TypeError) as e:
1 M$ _6 W# u2 ~8 d/ Q6 ?+ p( V - if 'required positional argument' in str(e):
3 {& v' g. Y6 i$ N& [! f7 k8 T; W1 @ - if sublime_api.can_accept_input(self.name(), args):! u8 a7 {, K, A- C: `. L% @
- sublime.active_window().run_command(4 p( x! T; G! C! c
- 'show_overlay',
2 F- x9 _' }/ n& @ Z9 D - {8 h1 d4 @! n* M# { Q" b; z
- 'overlay': 'command_palette',! U! K2 B- g$ s3 r' Z
- 'command': self.name(),3 ]. R5 O+ M. b2 b6 z1 g
- 'args': args; a% T" {* U: g& _/ m7 c$ z
- }( \, p+ b6 Q2 p2 `+ {
- )
9 `! V: W4 Z m - return
9 h Q# z3 y7 I, V1 b4 _ - raise) I0 C: b/ y5 N9 N6 c
- # `: W; P9 x& U7 Q# j/ S |
- def run(self):! C; {1 s, y7 L" T+ N8 f
- pass& n9 j) ?9 S# E& W) Q
- 1 N9 Z# O- x$ U& Y
- 0 b% Q" o ?9 \" S" K2 S
- class WindowCommand(Command):
$ Q: ]% x0 l5 N0 j/ o2 z- G - def __init__(self, window):
2 ?; S( e0 T" S* P" C8 T - self.window = window
+ U% f0 m! L( K6 o( s2 m: v - ; ^( ?' z* ^/ V0 A2 ^- g. B D4 V
- def run_(self, edit_token, args):
, r0 G( i& K: ?3 I. f- y - args = self.filter_args(args); |' Q8 P y f
- try:: B( \- z: _/ U( R K( p
- if args:* [3 H" q1 X; r( X" j7 u, f) Q
- return self.run(**args)8 x: `4 ~; a1 @+ o% k& n* z
- else:6 c" `% A; v! v5 R0 U
- return self.run()/ t. E: P# R$ a$ b) s
- except (TypeError) as e:
& T9 M5 n ^! j. a$ J% K - if 'required positional argument' in str(e):
% L1 t6 x* C2 [0 [% x - if sublime_api.window_can_accept_input(self.window.id(), self.name(), args):
0 q- ~, z' }" X8 | - sublime_api.window_run_command(
; \/ k+ G1 P6 `+ S' L' D: t& ?$ | - self.window.id(),
) z- J' D: n# ~7 d, z9 C - 'show_overlay',+ _9 [ X% {. z5 ~
- {9 C* v8 @, X* A, ?8 ^3 p
- 'overlay': 'command_palette',
- T! {$ x$ S- I# P" |0 i - 'command': self.name(),- N% L/ a) e3 T( ~
- 'args': args. U. w8 b n- ^" W0 r* O2 M4 |' S0 J# l
- }
$ x p+ U9 o/ ^2 x' Q& Q7 N - ) I* d, }7 q5 ^0 R
- return b, v0 Q6 n( ^4 N) k3 K/ E
- raise6 ?0 o- n! o0 {: L/ S5 ?# [, X
+ K, V$ H& r' Z$ S; ^- def run(self):
) [5 E2 |/ O* h6 b - pass
) Y) G3 ~; l9 ?/ Y+ ^+ T0 J
( I/ L: a# `: ^
, Q) b% K3 Y; H; j8 _- class TextCommand(Command):
7 r% e) a4 x7 w; ?" o" H. x& E* c3 u - def __init__(self, view):
7 l/ a) R+ t0 B - self.view = view- }: q! p1 j$ k6 M
- * i Z$ T* Y( A: N8 A8 Q6 T4 h
- def run_(self, edit_token, args):0 j- [' G6 o5 O' ]
- args = self.filter_args(args)
! [$ u! }6 H' y) B" n - try:6 E! C* {3 _3 S! G2 V
- if args:6 b3 k* M4 }( f2 N
- edit = self.view.begin_edit(edit_token, self.name(), args)
, ?! o% j- F7 `5 Y3 y - try:3 k8 j1 c2 R0 S
- return self.run(edit, **args)9 H7 r# \4 A) i* `
- finally:
. |; b0 `( E2 W( i - self.view.end_edit(edit). A; x; w) l+ a2 W* u
- else:6 F9 S3 ^6 S) H! i+ _
- edit = self.view.begin_edit(edit_token, self.name())$ X% I" T( ]+ p! u8 P% V
- try:- S- Z# Y9 W( g1 E+ U
- return self.run(edit)
7 Y6 q. f1 b- N' H: Z - finally:
; m4 V( n) S) | x3 ?7 t - self.view.end_edit(edit). q! _) K( ]: @7 C3 C5 U
- except (TypeError) as e: G P5 _# w; @4 O
- if 'required positional argument' in str(e):
3 T, b! a; Q) x1 Y, k6 l: }1 {) R. K - if sublime_api.view_can_accept_input(self.view.id(), self.name(), args):5 }8 h/ ]' Y; L& s& b+ F: q
- sublime_api.window_run_command(, t+ v3 {) N" }! G/ [$ y; E
- sublime_api.view_window(self.view.id()),
3 Q4 ?2 ?" O/ l# h! F, [$ F' Z - 'show_overlay',
: s+ a8 X& M' l/ f0 I - {
' w% p! B) @$ `! t - 'overlay': 'command_palette',
; W4 l: {9 N# W* E/ I - 'command': self.name(),
! X, _$ |- C. J1 Z5 G+ @9 Y - 'args': args
y9 `6 B- ^" j - }7 B1 g( t; P* _
- ): J- d( h! |: E7 g' D1 V4 ^. O& g
- return7 \( l, K9 u/ ? a5 d
- raise
# X/ ]' V/ Q7 [. |* c( a( D! L
0 F3 X0 [1 l; p$ N3 Q- def run(self, edit):
! d' m8 Z @3 Z2 c# L* V o - pass
+ F) `% I- L' Y h - , F% u( t" L# C
$ j3 T* g- U& `" O$ g- class EventListener(object):
J# @6 A& ?* f3 H5 P j9 p - pass
$ ?$ j- d9 j2 i( A% Q0 U3 h# b
: F) w3 M6 ]6 _5 L. g( {- s- + n/ U2 ?' y8 l' _
- class ViewEventListener(object):4 m: q, `* e! U! J) i
- @classmethod
* m" L( Y7 B& c$ A9 B - def is_applicable(cls, settings):
6 E8 S" y& _3 E5 \' O' \( `/ p$ u - return True
6 a8 o0 {: v) U+ x4 y: J - - _5 V9 W5 J: H& r" q! s$ q- h: C
- @classmethod
) g8 @7 A _# k8 v j4 a - def applies_to_primary_view_only(cls):2 _" ^1 a- o; N W- t. D, |
- return True0 `7 D/ |1 [5 f- v6 [$ w8 }
- , Y* K2 d$ v# X4 X0 k
- def __init__(self, view):( d8 `) ~- X/ P- ^
- self.view = view- k1 S; s9 W( H5 F
! g" ?; @& M, M6 \- Z, E! |
; Y# d1 i! ?/ P4 H. p' S+ o- class MultizipImporter(object):2 n/ m8 K$ a4 `2 U1 a
- def __init__(self):9 n; M I6 ~5 Z) |
- self.loaders = []6 e! x- _; l9 R
- self.file_loaders = []5 L2 Z& p6 r0 R, ~; [- v6 Y
6 ?4 }. M4 o9 r; y: T: z- def find_module(self, fullname, path=None):
1 R; \8 J/ s, j' S# Y - if not path:
* _6 H4 _1 x1 k3 l' x - for l in self.loaders:5 P( E, n/ F A& m
- if l.name == fullname:
, N8 P1 V9 r# h1 H! m P - return l
( p' V! w0 I1 ?& w) K0 q$ Y - & \: P: ?2 E |, G
- for l in self.loaders:4 e. ?; H. ~, X% n( L1 @
- if path == [l.zippath]:
; Z' I' ?$ P8 F7 G2 s - if l.has(fullname):
1 a8 d. G$ \- P0 d* C3 ~1 c% Y - return l
" `% H& R4 O) H( j. H - : ^" y. ]9 O6 z3 w
- return None! x. Z$ x- A }6 a
- 0 k0 P$ l5 B& Q
- 0 |& I9 u9 K( g8 ?3 k
- class ZipLoader(object):
3 m; T6 u1 a4 ~, M4 t" a0 G- ? - def __init__(self, zippath):- w4 f8 t$ _5 L% c/ l& j$ ~) Y- N3 L; V& p
- self.zippath = zippath
; J6 _6 p' a; v W+ X3 W7 G% h - self.name = os.path.splitext(os.path.basename(zippath))[0]% t- O' ~& M# i/ W5 D
- self._scan_zip()
3 P! Z3 q# n8 ` L t* o# H7 U - ; |1 J. e! K1 f9 b; T1 B @
- def has(self, fullname):9 v* |/ Y0 f5 ] F# r
- name, key = fullname.split('.', 1)6 W. _" _+ K: I* D+ f, {' ]6 q' s
- if name == self.name and key in self.contents:
& A- Y& \+ j- n2 M# ]1 w. a: I. d' O - return True2 T* M2 c$ t* J+ `) W; j
- . h; g7 k* Z9 G1 r5 \1 @
- override_file = os.path.join(override_path, os.sep.join(fullname.split('.')) + '.py')8 l4 H$ i- ~# ]. S4 l- V, F8 P6 j
- if os.path.isfile(override_file):2 G4 M8 V+ q$ S
- return True
w {( E5 O9 O; ] - / |; h6 |# J4 f8 J4 y5 _, X
- override_package = os.path.join(override_path, os.sep.join(fullname.split('.')))! O" }1 a! }/ h X/ J. d8 K r0 j! M
- if os.path.isdir(override_package):' B& X, v- e$ O! z* T$ q) ~7 Z6 L
- return True- G6 C; s3 x, a. m) x0 _! W, _5 z
* h' ?; c4 X# Y7 ^- return False' O' L- ]7 e8 U+ r/ @
: F, d: W1 u# o- g2 x6 e& G' S- def load_module(self, fullname):$ E2 v \8 l+ s% Z
- # Only if a module is being reloaded and hasn't been scanned recently
) z! ^, ~( o) `9 E1 ^% r% C" }: b - # do we force a refresh of the contents of the .sublime-package. This9 d3 k# y& A6 q5 {
- # allows proper code upgrades using Package Control.( R8 C& `' O; i' }. l5 K
- if fullname in imp._RELOADING:
: K9 o# B8 F. e - if self.refreshed < time.time() - 5:! P0 j9 H5 @4 n% X
- self._scan_zip()2 l) a, f3 q+ p: t0 v+ {% B
" T, G' R, X7 t" C. o! ~- source, source_path, is_pkg = self._read_source(fullname)
6 C% G! }2 w: O. V( x' x$ @
! n. w5 M! {# v& Q4 @- if source is None:; \% L0 C+ M# N
- raise ImportError("No module named '%s'" % fullname)
" ]0 _6 z7 A8 X5 i - , {1 H4 M$ U' D4 ]. ~. u, M7 \" |) ~
- is_new = False# H$ R; N7 e) m0 z/ k7 _3 _7 L+ W
- if fullname in sys.modules:
7 m0 N+ m( `, }) D: u. c& K0 c - mod = sys.modules[fullname], Z% z3 d* s4 ~+ y5 U
- old_mod_file = mod.__file__
2 @4 i4 D ^6 O( p- f+ ~( ~ - else:! w7 F4 f7 R. e4 N
- is_new = True
, w" Z# Y/ @3 p& x - mod = sys.modules.setdefault(fullname, imp.new_module(fullname))
" Q# y& s( x8 Z" E7 A5 Y1 M - mod.__name__ = fullname
2 c2 a# z/ l! q1 k1 O5 F - mod.__path__ = [self.zippath]
L. z# _9 e9 o+ |; G1 { - mod.__loader__ = self
$ w/ w* X) J5 J2 T% Y% ?! J3 d - % n: `. E" G& }: F
- mod.__file__ = source_path% M0 \' P% ~, o* n* z# s9 Q
" ]/ g; P" }9 e4 d. g; b B, V1 B- if is_pkg:
9 Y, Q t( h' ` - mod.__package__ = mod.__name__
$ z, H J' j) f! g4 i - else:
* o/ H0 h: {9 p7 G" ~- i - mod.__package__ = fullname.rpartition('.')[0]
; j. Y2 q- t" l
/ B8 L4 m; s7 s p0 A( r- try:
" l0 F7 @$ a, x - exec(compile(source, source_path, 'exec'), mod.__dict__)
$ Y- u2 U9 f9 B, Q- E - return mod! [: F: i, S, f) j! |" U: N- [
& z) s, e; ~- ^ s; f4 Q3 M, w9 Q7 d- except:
$ F( |8 T% M6 }* G8 N - if is_new:
' M- `* v, S: ~/ ]+ e' G& { - del sys.modules[fullname]
8 Y' c8 t" s: o' m/ J Y - else:! X; [3 h4 w/ ^ X& y
- mod.__file__ = old_mod_file2 X ^9 \2 J8 f! D( Q# N
- raise4 _+ X! M8 @. v, T' ?
6 _& e: u2 m( A+ A( }$ o- def get_source(self, fullname):
4 i& m0 y7 k4 m2 x, O2 d - name, key = fullname.split('.', 1)$ n; D: ^) l2 t
- if name != self.name:4 q# ]( ?$ n5 J3 _: g
- return None7 x+ G8 ^2 }! W$ j2 j a3 ?! A
- source, _, _ = self._read_source(fullname)) Z/ h. z; E* l! a+ O8 X: s- _
- return source0 h5 ~/ A" }6 C
- % l0 p9 y5 `1 R( V% @& u) M! D
- def _read_source(self, fullname):
: {: V3 F2 x3 j: a5 N- v - name_parts = fullname.split('.')1 S" X- A/ d. o& ]# T- a+ B
- override_basename = os.path.join(override_path, *name_parts)
, M) Q& H) I. @0 o0 x7 ~# J - override_py = override_basename + '.py'
3 j( y8 h/ ?9 l- I& W. } - override_init = os.path.join(override_basename, '__init__.py')7 y8 S- a7 ` I
- 1 l8 G3 t9 S; }" m
- if os.path.isfile(override_py):
# J7 @0 j, [, {; y7 x - try:$ C$ s. P; l4 I' Q- O4 s
- with open(override_py, 'r', encoding='utf-8') as f:) o N/ j. k X; B, x8 ?
- return (f.read(), override_py, False)
5 S S2 a6 w6 F% \: q - except (Exception) as e:( a/ U' L3 s0 x
- print(override_py, 'could not be read:', e)2 v& p: D& P* O' s% E( q5 j
- 9 @+ C+ H4 ]+ T+ y0 T }
- if os.path.isfile(override_init):
8 _) Y% Z3 D# @( M - try:- n9 m/ m6 p& m( }3 l- k
- with open(override_init, 'r', encoding='utf-8') as f:
+ o$ s1 r2 k, |! ] - return (f.read(), override_init, True)
* Z/ ]8 V* U: x" ~ - except (Exception) as e:* V( l3 S: C9 b5 {5 _, l+ T
- print(override_init, 'could not be read:', e)
! P* n, [. ^& v
: U# t! z& N! Z- key = '.'.join(name_parts[1:])
+ V8 S& m! u6 C1 @$ v3 ~9 \0 M - if key in self.contents:% M4 X/ s) {& U+ ?: N1 Z f
- source = self.contents[key]
- R" Z" N+ W5 e' w* e; ]/ J# ?7 _2 H - source_path = os.path.join(self.zippath, self.filenames[key]).rstrip(os.sep)6 i8 S2 e$ a1 h, K
- is_pkg = key in self.packages2 X" u3 ^: G7 D' o
- return (source, source_path, is_pkg)
2 V* a( a' z! I$ D/ a5 z- i* s& `
. U* T, ?, M3 F. h' t- # This allows .py overrides to exist in subfolders that:
( X1 Y+ f y$ m5 r; L6 _ _) K - # 1. Do not exist in the .sublime-package file4 d- [5 V! l1 O0 g1 n
- # 2. Do not contain an __init__.py$ h2 Y: y6 X, }# P. q. x
- if os.path.isdir(override_basename):# G" j7 b& g! {8 O) ~9 d
- return ('', override_basename, True)
4 ]0 U# H8 `( r' ?
/ E' x4 }7 T. Y# k- return (None, None, False)3 w& c% V) s* U) j. l; v" R$ S
" h Y7 P/ d2 y: B/ z. s" [3 X- def _scan_zip(self):
- E: @0 |" @7 l o, ^% O' Z - self.contents = {"": ""}
' |+ e* F4 h1 c: c: x& Q; E" d5 n; c - self.filenames = {"": ""}
5 u' g M! b# ?. ?+ G5 H. _5 ] - self.packages = {""}
( T0 p7 Y) a9 s: Z3 U - self.refreshed = time.time() n$ I/ N* b; {( U/ {! d! R
- + x* W+ y' q) f9 Y" W
- try:
1 N% {$ @, ] [1 o, u U - with zipfile.ZipFile(self.zippath, 'r') as z:, c- p2 m* I6 ~& G9 H
- files = [i.filename for i in z.infolist()]
6 E: U- ^8 T0 q5 x L' e( ^
9 {; h* i: k m- for f in files:
' I; s) K1 I% K, s" M9 B - base, ext = os.path.splitext(f)
# n# }4 m4 V% s9 ^8 Z - if ext != ".py":
! s- A( n$ f1 e1 \ Z1 N0 r; ~* U - continue9 W: A E$ B! W
' i$ [3 E( ]9 P% Q! E1 [4 S- paths = base.split('/')0 O) o6 M/ Q q' P9 D# ]
- if len(paths) > 0 and paths[len(paths) - 1] == "__init__":
( t1 p! R" P: t8 }* k - paths.pop(); [' x3 y$ I, v/ H- g* H' T
- self.packages.add('.'.join(paths))2 I' }/ [5 Z5 e2 v
; c8 s. U s- A5 u) m, Z0 P8 ~- try:
% D7 V0 v0 q( R - pkg_path = '.'.join(paths)- |0 {, {7 D, M4 T9 e* `
- self.contents[pkg_path] = z.read(f).decode('utf-8')9 o' e* [8 r; O: G3 C
- self.filenames[pkg_path] = f- a* e# ~( s/ S8 z2 B
- except UnicodeDecodeError:
( o. C) I0 |1 |5 S+ q6 \" {- I - print(f, "in", self.zippath, "is not utf-8 encoded, unable to load plugin")
! n1 f9 a; |- ?+ P - continue& {$ Y. o. S# u( e) L0 @
- . `+ ?' O& B& e H8 B7 T) f
- while len(paths) > 1:/ ^* k- j ^- ?0 t
- paths.pop()
0 k4 B J* f U( k - parent = '.'.join(paths)
8 V$ J2 Q5 ^$ p, c9 K0 I6 H4 W - if parent not in self.contents:1 u% T1 l) H4 e R. ]9 e6 I
- self.contents[parent] = ""8 G! z, i5 N4 T- S. T& A {: i
- self.filenames[parent] = parent) d. \4 ~7 [5 U3 L0 r. C& R
- self.packages.add(parent)
* z3 y8 u ^! S$ l, s/ I - except (Exception) as e:
: ~. k# H4 U1 v! ]( A - print("Error loading %s:" % self.zippath, e)
2 U2 {% F% s) o& \3 f( I6 T - $ N7 N0 r9 j/ r! \! K
- : o0 G9 u$ v! Y8 i- H# w
- override_path = None
$ t0 u) a& N' u8 U# ] - multi_importer = MultizipImporter()
) l; s7 d! D( y! |4 T. H. ] - sys.meta_path.insert(0, multi_importer)7 q k3 g: \9 v" S$ D
- % r; j+ d. W# i* H% H: O2 {1 U
- , c% F0 P* A A
- def update_compressed_packages(pkgs):. j7 I7 B& a9 I& b( {
- multi_importer.loaders = []
" m4 a8 f+ M2 r% d0 O+ x - for p in pkgs:
+ |+ U' l' n6 U# s* n' K3 \ - try:; g. W5 d6 ?. v$ b1 L
- multi_importer.loaders.append(ZipLoader(p))- G: w! c/ i% q% K4 p
- except (FileNotFoundError, zipfile.BadZipFile) as e:) M% A( Z) ^* e9 D( W4 Z7 J
- print("error loading " + p + ": " + str(e))* q6 @. T [1 P0 E: ] n% o0 a
, s [3 k+ D" ?, `; S5 o
6 A4 M4 A7 `* t- ?7 L3 f- def set_override_path(path):
) K- @) [) v- B5 |+ S - global override_path
, W# D. R, O4 }* f6 z* h; F/ p - override_path = path; t, v. g% w- @; k: Y& z
复制代码 $ Y+ [. U9 N- V0 V3 N! e# k8 D. ]
! [5 k" A0 W# N5 l$ ?
8 F( v" ]# D: ]7 J( V
5 ^, A; P# [( W8 j |
|