@@ -12,18 +12,14 @@ use fuzzy_matcher::skim::SkimMatcherV2 as Matcher;
12
12
use tui:: widgets:: Widget ;
13
13
14
14
use std:: { cmp:: Ordering , time:: Instant } ;
15
- use std:: {
16
- collections:: HashMap ,
17
- io:: Read ,
18
- path:: { Path , PathBuf } ,
19
- } ;
15
+ use std:: { collections:: HashMap , io:: Read , path:: PathBuf } ;
20
16
21
17
use crate :: ui:: { Prompt , PromptEvent } ;
22
18
use helix_core:: { movement:: Direction , Position } ;
23
19
use helix_view:: {
24
20
editor:: Action ,
25
21
graphics:: { CursorKind , Margin , Modifier , Rect } ,
26
- Document , Editor ,
22
+ Document , DocumentId , Editor ,
27
23
} ;
28
24
29
25
use super :: menu:: Item ;
@@ -32,8 +28,36 @@ pub const MIN_AREA_WIDTH_FOR_PREVIEW: u16 = 72;
32
28
/// Biggest file size to preview in bytes
33
29
pub const MAX_FILE_SIZE_FOR_PREVIEW : u64 = 10 * 1024 * 1024 ;
34
30
31
+ #[ derive( PartialEq , Eq , Hash ) ]
32
+ pub enum PathOrId {
33
+ Id ( DocumentId ) ,
34
+ Path ( PathBuf ) ,
35
+ }
36
+
37
+ impl PathOrId {
38
+ fn get_canonicalized ( self ) -> std:: io:: Result < Self > {
39
+ use PathOrId :: * ;
40
+ Ok ( match self {
41
+ Path ( path) => Path ( helix_core:: path:: get_canonicalized_path ( & path) ?) ,
42
+ Id ( id) => Id ( id) ,
43
+ } )
44
+ }
45
+ }
46
+
47
+ impl From < PathBuf > for PathOrId {
48
+ fn from ( v : PathBuf ) -> Self {
49
+ Self :: Path ( v)
50
+ }
51
+ }
52
+
53
+ impl From < DocumentId > for PathOrId {
54
+ fn from ( v : DocumentId ) -> Self {
55
+ Self :: Id ( v)
56
+ }
57
+ }
58
+
35
59
/// File path and range of lines (used to align and highlight lines)
36
- pub type FileLocation = ( PathBuf , Option < ( usize , usize ) > ) ;
60
+ pub type FileLocation = ( PathOrId , Option < ( usize , usize ) > ) ;
37
61
38
62
pub struct FilePicker < T : Item > {
39
63
picker : Picker < T > ,
@@ -112,62 +136,71 @@ impl<T: Item> FilePicker<T> {
112
136
self . picker
113
137
. selection ( )
114
138
. and_then ( |current| ( self . file_fn ) ( editor, current) )
115
- . and_then ( |( path, line) | {
116
- helix_core:: path:: get_canonicalized_path ( & path)
117
- . ok ( )
118
- . zip ( Some ( line) )
119
- } )
139
+ . and_then ( |( path_or_id, line) | path_or_id. get_canonicalized ( ) . ok ( ) . zip ( Some ( line) ) )
120
140
}
121
141
122
142
/// Get (cached) preview for a given path. If a document corresponding
123
143
/// to the path is already open in the editor, it is used instead.
124
144
fn get_preview < ' picker , ' editor > (
125
145
& ' picker mut self ,
126
- path : & Path ,
146
+ path_or_id : PathOrId ,
127
147
editor : & ' editor Editor ,
128
148
) -> Preview < ' picker , ' editor > {
129
- if let Some ( doc) = editor. document_by_path ( path) {
130
- return Preview :: EditorDocument ( doc) ;
131
- }
149
+ match path_or_id {
150
+ PathOrId :: Path ( path) => {
151
+ let path = & path;
152
+ if let Some ( doc) = editor. document_by_path ( path) {
153
+ return Preview :: EditorDocument ( doc) ;
154
+ }
132
155
133
- if self . preview_cache . contains_key ( path) {
134
- return Preview :: Cached ( & self . preview_cache [ path] ) ;
135
- }
156
+ if self . preview_cache . contains_key ( path) {
157
+ return Preview :: Cached ( & self . preview_cache [ path] ) ;
158
+ }
136
159
137
- let data = std:: fs:: File :: open ( path) . and_then ( |file| {
138
- let metadata = file. metadata ( ) ?;
139
- // Read up to 1kb to detect the content type
140
- let n = file. take ( 1024 ) . read_to_end ( & mut self . read_buffer ) ?;
141
- let content_type = content_inspector:: inspect ( & self . read_buffer [ ..n] ) ;
142
- self . read_buffer . clear ( ) ;
143
- Ok ( ( metadata, content_type) )
144
- } ) ;
145
- let preview = data
146
- . map (
147
- |( metadata, content_type) | match ( metadata. len ( ) , content_type) {
148
- ( _, content_inspector:: ContentType :: BINARY ) => CachedPreview :: Binary ,
149
- ( size, _) if size > MAX_FILE_SIZE_FOR_PREVIEW => CachedPreview :: LargeFile ,
150
- _ => {
151
- // TODO: enable syntax highlighting; blocked by async rendering
152
- Document :: open ( path, None , None )
153
- . map ( |doc| CachedPreview :: Document ( Box :: new ( doc) ) )
154
- . unwrap_or ( CachedPreview :: NotFound )
155
- }
156
- } ,
157
- )
158
- . unwrap_or ( CachedPreview :: NotFound ) ;
159
- self . preview_cache . insert ( path. to_owned ( ) , preview) ;
160
- Preview :: Cached ( & self . preview_cache [ path] )
160
+ let data = std:: fs:: File :: open ( path) . and_then ( |file| {
161
+ let metadata = file. metadata ( ) ?;
162
+ // Read up to 1kb to detect the content type
163
+ let n = file. take ( 1024 ) . read_to_end ( & mut self . read_buffer ) ?;
164
+ let content_type = content_inspector:: inspect ( & self . read_buffer [ ..n] ) ;
165
+ self . read_buffer . clear ( ) ;
166
+ Ok ( ( metadata, content_type) )
167
+ } ) ;
168
+ let preview = data
169
+ . map (
170
+ |( metadata, content_type) | match ( metadata. len ( ) , content_type) {
171
+ ( _, content_inspector:: ContentType :: BINARY ) => CachedPreview :: Binary ,
172
+ ( size, _) if size > MAX_FILE_SIZE_FOR_PREVIEW => {
173
+ CachedPreview :: LargeFile
174
+ }
175
+ _ => {
176
+ // TODO: enable syntax highlighting; blocked by async rendering
177
+ Document :: open ( path, None , None )
178
+ . map ( |doc| CachedPreview :: Document ( Box :: new ( doc) ) )
179
+ . unwrap_or ( CachedPreview :: NotFound )
180
+ }
181
+ } ,
182
+ )
183
+ . unwrap_or ( CachedPreview :: NotFound ) ;
184
+ self . preview_cache . insert ( path. to_owned ( ) , preview) ;
185
+ Preview :: Cached ( & self . preview_cache [ path] )
186
+ }
187
+ PathOrId :: Id ( id) => {
188
+ let doc = editor. documents . get ( & id) . unwrap ( ) ;
189
+ Preview :: EditorDocument ( doc)
190
+ }
191
+ }
161
192
}
162
193
163
194
fn handle_idle_timeout ( & mut self , cx : & mut Context ) -> EventResult {
164
195
// Try to find a document in the cache
165
196
let doc = self
166
197
. current_file ( cx. editor )
167
- . and_then ( |( path, _range) | self . preview_cache . get_mut ( & path) )
168
- . and_then ( |cache| match cache {
169
- CachedPreview :: Document ( doc) => Some ( doc) ,
170
- _ => None ,
198
+ . and_then ( |( path, _range) | match path {
199
+ PathOrId :: Id ( doc_id) => Some ( doc_mut ! ( cx. editor, & doc_id) ) ,
200
+ PathOrId :: Path ( path) => match self . preview_cache . get_mut ( & path) {
201
+ Some ( CachedPreview :: Document ( doc) ) => Some ( doc) ,
202
+ _ => None ,
203
+ } ,
171
204
} ) ;
172
205
173
206
// Then attempt to highlight it if it has no language set
@@ -224,7 +257,7 @@ impl<T: Item + 'static> Component for FilePicker<T> {
224
257
block. render ( preview_area, surface) ;
225
258
226
259
if let Some ( ( path, range) ) = self . current_file ( cx. editor ) {
227
- let preview = self . get_preview ( & path, cx. editor ) ;
260
+ let preview = self . get_preview ( path, cx. editor ) ;
228
261
let doc = match preview. document ( ) {
229
262
Some ( doc) => doc,
230
263
None => {
0 commit comments