1+ use std:: sync:: Arc ;
2+
13use collections:: HashSet ;
2- use editor:: Editor ;
3- use gpui:: { Entity , WeakEntity } ;
4+ use editor:: {
5+ Editor ,
6+ actions:: { RestartLanguageServer , StopLanguageServer } ,
7+ } ;
8+ use gpui:: { Corner , Entity , WeakEntity } ;
9+ use language:: CachedLspAdapter ;
10+ use lsp:: LanguageServer ;
411use project:: LspStore ;
5- use ui:: { IconButtonShape , Tooltip , prelude:: * } ;
12+ use ui:: { ContextMenu , IconButtonShape , PopoverMenu , PopoverMenuHandle , Tooltip , prelude:: * } ;
613use workspace:: { StatusItemView , Workspace } ;
714
815pub struct LspTool {
916 active_editor : Option < WeakEntity < Editor > > ,
1017 lsp_store : Entity < LspStore > ,
18+ popover_menu_handle : PopoverMenuHandle < ContextMenu > ,
1119}
1220
1321impl LspTool {
14- pub fn new ( workspace : & Workspace , cx : & App ) -> Self {
22+ pub fn new (
23+ popover_menu_handle : PopoverMenuHandle < ContextMenu > ,
24+ workspace : & Workspace ,
25+ cx : & App ,
26+ ) -> Self {
1527 let lsp_store = workspace. project ( ) . read ( cx) . lsp_store ( ) ;
1628 Self {
1729 active_editor : None ,
30+ popover_menu_handle,
1831 lsp_store,
1932 }
2033 }
34+
35+ fn build_lsp_context_menu (
36+ & self ,
37+ editor : WeakEntity < Editor > ,
38+ applicable_language_servers : & [ ( Arc < CachedLspAdapter > , Arc < LanguageServer > ) ] ,
39+ window : & mut Window ,
40+ cx : & mut Context < Self > ,
41+ ) -> Entity < ContextMenu > {
42+ ContextMenu :: build ( window, cx, move |menu, _, cx| {
43+ menu. separator ( )
44+ . entry (
45+ "Restart all servers" ,
46+ Some ( Box :: new ( RestartLanguageServer ) ) ,
47+ {
48+ let editor = editor. clone ( ) ;
49+ move |window, cx| {
50+ editor
51+ . update ( cx, |editor, cx| {
52+ editor. restart_language_server (
53+ & RestartLanguageServer ,
54+ window,
55+ cx,
56+ ) ;
57+ } )
58+ . ok ( ) ;
59+ }
60+ } ,
61+ )
62+ . entry (
63+ "Stop all servers" ,
64+ Some ( Box :: new ( StopLanguageServer ) ) ,
65+ move |window, cx| {
66+ editor
67+ . update ( cx, |editor, cx| {
68+ // TODO kb this will make the button disappear.
69+ // We need a better method to get "all language servers and statuses"
70+ editor. stop_language_server ( & StopLanguageServer , window, cx) ;
71+ } )
72+ . ok ( ) ;
73+ } ,
74+ )
75+ } )
76+ }
2177}
2278
2379impl StatusItemView for LspTool {
@@ -51,7 +107,7 @@ impl Render for LspTool {
51107
52108 let buffers = editor. read ( cx) . buffer ( ) . read ( cx) . all_buffers ( ) ;
53109 let mut server_ids = HashSet :: default ( ) ;
54- let applicable_language_servers = self . lsp_store . update ( cx, |lsp_store, cx| {
110+ let applicable_language_servers = Arc :: new ( self . lsp_store . update ( cx, |lsp_store, cx| {
55111 buffers
56112 . iter ( )
57113 . flat_map ( |buffer| {
@@ -64,21 +120,34 @@ impl Render for LspTool {
64120 } )
65121 } )
66122 . collect :: < Vec < _ > > ( )
67- } ) ;
68- dbg ! ( applicable_language_servers. len( ) ) ;
123+ } ) ) ;
69124 if applicable_language_servers. is_empty ( ) {
70125 return div ( ) ;
71126 }
72127
73- div ( ) . child (
74- IconButton :: new ( "zed-lsp-tool-button" , IconName :: Bolt )
75- . shape ( IconButtonShape :: Square )
76- . icon_size ( IconSize :: XSmall )
77- . indicator_border_color ( Some ( cx. theme ( ) . colors ( ) . status_bar_background ) )
78- . tooltip ( move |_, cx| Tooltip :: simple ( "Language servers" , cx) )
79- . on_click ( cx. listener ( move |_, _, _window, _cx| {
80- dbg ! ( "????????" ) ;
81- } ) ) ,
82- )
128+ let icon_button = IconButton :: new ( "zed-lsp-tool-button" , IconName :: Bolt )
129+ . shape ( IconButtonShape :: Square )
130+ . icon_size ( IconSize :: XSmall )
131+ . indicator_border_color ( Some ( cx. theme ( ) . colors ( ) . status_bar_background ) )
132+ . tooltip ( move |_, cx| Tooltip :: simple ( "Language servers" , cx) ) ;
133+
134+ let lsp_tool = cx. entity ( ) . clone ( ) ;
135+
136+ let popover_menu = PopoverMenu :: new ( "lsp_servers" )
137+ . menu ( move |window, cx| {
138+ Some ( lsp_tool. update ( cx, |lsp_tool, cx| {
139+ lsp_tool. build_lsp_context_menu (
140+ editor. downgrade ( ) ,
141+ & applicable_language_servers,
142+ window,
143+ cx,
144+ )
145+ } ) )
146+ } )
147+ . anchor ( Corner :: BottomRight )
148+ . with_handle ( self . popover_menu_handle . clone ( ) )
149+ . trigger ( icon_button) ;
150+
151+ div ( ) . child ( popover_menu. into_any_element ( ) )
83152 }
84153}
0 commit comments