11use std:: path:: Path ;
22use std:: path:: PathBuf ;
33
4- use crate :: compositor:: Compositor ;
4+ use crate :: compositor:: Component ;
55use crate :: ui;
66use crate :: ui:: PromptEvent ;
77use anyhow:: anyhow;
@@ -11,7 +11,6 @@ use helix_view::events::DocumentDidOpen;
1111use helix_view:: handlers:: Handlers ;
1212use helix_view:: theme:: Modifier ;
1313use helix_view:: theme:: Style ;
14- use helix_view:: Editor ;
1514use tui:: text:: Span ;
1615use ui:: overlay:: overlaid;
1716
@@ -49,13 +48,9 @@ impl AsRef<str> for TrustOptions {
4948 }
5049 }
5150}
52- pub fn trust_dialog ( editor : & mut Editor , compositor : & mut Compositor ) {
53- let Some ( file_path) = doc ! ( editor) . path ( ) else {
54- // helix doesn't send the document open event when it has no paths, but the user may still use :trust-dialog anyways.
55- editor. set_error ( "Could not open trust dialog: the file does not have a path." ) ;
56- return ;
57- } ;
58- let ( path, is_file) = helix_loader:: find_workspace_in ( file_path) ;
51+
52+ pub fn trust_dialog ( path : impl AsRef < Path > ) -> impl Component + ' static {
53+ let ( path, is_file) = helix_loader:: find_workspace_in ( path. as_ref ( ) ) ;
5954 let options = vec ! [
6055 TrustOptions :: DoNotTrust ,
6156 TrustOptions :: Trust ,
@@ -66,7 +61,7 @@ pub fn trust_dialog(editor: &mut Editor, compositor: &mut Compositor) {
6661 let path_clone = path. clone ( ) ;
6762 let warning = format ! ( "Trusting the {file_or_workspace} will allow the usage of LSPs, formatters, debuggers and workspace config, all of which can lead to remote code execution.
6863Ensure you trust the source of the {file_or_workspace} before trusting it." ) ;
69- let ui = ui:: Select :: new (
64+ ui:: Select :: new (
7065 format ! ( "Trust {file_or_workspace} '{}'?\n {warning}" , path. display( ) ) ,
7166 options,
7267 ( ) ,
@@ -81,19 +76,17 @@ Ensure you trust the source of the {file_or_workspace} before trusting it.");
8176 }
8277 PromptEvent :: Validate => ( ) ,
8378 }
79+
8480 let maybe_err = match option {
8581 TrustOptions :: Trust => editor. trust_workspace ( ) ,
8682 TrustOptions :: DoNotTrust => editor. untrust_workspace ( ) ,
8783 TrustOptions :: DistrustParent | TrustOptions :: TrustParent => {
8884 let path = path_clone. clone ( ) ;
8985 let option = option. clone ( ) ;
90- crate :: job:: dispatch_blocking ( move |editor, compositor| {
91- choose_parent_dialog (
92- path,
93- matches ! ( option, TrustOptions :: TrustParent ) ,
94- editor,
95- compositor,
96- )
86+ crate :: job:: dispatch_blocking ( move |_editor, compositor| {
87+ let dialog =
88+ choose_parent_dialog ( path, matches ! ( option, TrustOptions :: TrustParent ) ) ;
89+ compositor. push ( Box :: new ( overlaid ( dialog) ) )
9790 } ) ;
9891 Ok ( ( ) )
9992 }
@@ -102,17 +95,10 @@ Ensure you trust the source of the {file_or_workspace} before trusting it.");
10295 editor. set_error ( e. to_string ( ) )
10396 }
10497 } ,
105- ) ;
106-
107- compositor. push ( Box :: new ( overlaid ( ui) ) ) ;
98+ )
10899}
109100
110- fn choose_parent_dialog (
111- path : impl AsRef < Path > ,
112- trust : bool ,
113- _editor : & mut Editor ,
114- compositor : & mut Compositor ,
115- ) {
101+ fn choose_parent_dialog ( path : impl AsRef < Path > , trust : bool ) -> impl Component + ' static {
116102 let path = path. as_ref ( ) . to_path_buf ( ) ;
117103 let options = path
118104 . ancestors ( )
@@ -124,7 +110,7 @@ fn choose_parent_dialog(
124110 format ! ( "Workspace to {trust_or_untrust}" ) ,
125111 |path : & PathBuf , _| path. display ( ) . to_string ( ) . into ( ) ,
126112 ) ] ;
127- let picker = ui:: Picker :: new ( columns, 0 , options, ( ) , move |cx, path, _action| {
113+ ui:: Picker :: new ( columns, 0 , options, ( ) , move |cx, path, _action| {
128114 let result = if let Err ( e) = std:: fs:: create_dir ( path. join ( ".helix" ) ) {
129115 Err ( anyhow ! (
130116 "Couldn't make '{}' into a workspace: {e}" ,
@@ -144,8 +130,7 @@ fn choose_parent_dialog(
144130 cx. editor . set_error ( e. to_string ( ) ) ;
145131 }
146132 } )
147- . always_show_header ( true ) ;
148- compositor. push ( Box :: new ( overlaid ( picker) ) )
133+ . always_show_header ( true )
149134}
150135
151136pub ( super ) fn register_hooks ( _handlers : & Handlers ) {
@@ -154,11 +139,22 @@ pub(super) fn register_hooks(_handlers: &Handlers) {
154139 && event
155140 . editor
156141 . document( event. doc)
157- . is_some_and( |doc| doc. is_trusted. is_none( ) )
142+ . is_some_and( |doc| doc. path ( ) . is_some ( ) && doc . is_trusted. is_none( ) )
158143 {
144+ // these unwraps are fine due to the above. TODO: change this to if let chains once rust is bumped to 1.88
145+ let path = event
146+ . editor
147+ . document( event. doc)
148+ . unwrap( )
149+ . path( )
150+ . unwrap( )
151+ . to_path_buf( ) ;
152+ // we use tokio::spawn because crate::job::dispatch_blocking hangs on singular file.
153+ // Probably should investigate that.
159154 tokio:: spawn( async move {
160- crate :: job:: dispatch( move |editor, compositor| {
161- trust_dialog( editor, compositor) ;
155+ crate :: job:: dispatch( move |_, compositor| {
156+ let dialog = trust_dialog( path) ;
157+ compositor. push( Box :: new( dialog) ) ;
162158 } )
163159 . await ;
164160 } ) ;
0 commit comments