aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorA-Walrus2022-11-21 01:58:35 +0000
committerGitHub2022-11-21 01:58:35 +0000
commit2f9ca3840a478fc58f411b6a4bc67019829ff72f (patch)
treee26e340d317442b4d9e8ae8216ad40dc297a77ca
parent420e33a60064ad86e9f2f8dd29b3938318355673 (diff)
Add preview for scratch buffers in buffer picker (#3454)
-rw-r--r--helix-term/src/commands.rs6
-rw-r--r--helix-term/src/commands/dap.rs4
-rw-r--r--helix-term/src/commands/lsp.rs2
-rw-r--r--helix-term/src/ui/mod.rs2
-rw-r--r--helix-term/src/ui/picker.rs129
5 files changed, 88 insertions, 55 deletions
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index 1b0c557e..25f00f98 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -2005,7 +2005,7 @@ fn global_search(cx: &mut Context) {
align_view(doc, view, Align::Center);
},
|_editor, FileResult { path, line_num }| {
- Some((path.clone(), Some((*line_num, *line_num))))
+ Some((path.clone().into(), Some((*line_num, *line_num))))
},
);
compositor.push(Box::new(overlayed(picker)));
@@ -2360,7 +2360,7 @@ fn buffer_picker(cx: &mut Context) {
.selection(view_id)
.primary()
.cursor_line(doc.text().slice(..));
- Some((meta.path.clone()?, Some((line, line))))
+ Some((meta.id.into(), Some((line, line))))
},
);
cx.push_layer(Box::new(overlayed(picker)));
@@ -2441,7 +2441,7 @@ fn jumplist_picker(cx: &mut Context) {
|editor, meta| {
let doc = &editor.documents.get(&meta.id)?;
let line = meta.selection.primary().cursor_line(doc.text().slice(..));
- Some((meta.path.clone()?, Some((line, line))))
+ Some((meta.path.clone()?.into(), Some((line, line))))
},
);
cx.push_layer(Box::new(overlayed(picker)));
diff --git a/helix-term/src/commands/dap.rs b/helix-term/src/commands/dap.rs
index c27417e3..b182f28c 100644
--- a/helix-term/src/commands/dap.rs
+++ b/helix-term/src/commands/dap.rs
@@ -85,7 +85,7 @@ fn thread_picker(
frame.line.saturating_sub(1),
frame.end_line.unwrap_or(frame.line).saturating_sub(1),
));
- Some((path, pos))
+ Some((path.into(), pos))
},
);
compositor.push(Box::new(picker));
@@ -706,7 +706,7 @@ pub fn dap_switch_stack_frame(cx: &mut Context) {
.and_then(|source| source.path.clone())
.map(|path| {
(
- path,
+ path.into(),
Some((
frame.line.saturating_sub(1),
frame.end_line.unwrap_or(frame.line).saturating_sub(1),
diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs
index 33d33440..dcabfab1 100644
--- a/helix-term/src/commands/lsp.rs
+++ b/helix-term/src/commands/lsp.rs
@@ -156,7 +156,7 @@ fn location_to_file_location(location: &lsp::Location) -> FileLocation {
location.range.start.line as usize,
location.range.end.line as usize,
));
- (path, line)
+ (path.into(), line)
}
// TODO: share with symbol picker(symbol.location)
diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs
index cca9e9bf..3416b319 100644
--- a/helix-term/src/ui/mod.rs
+++ b/helix-term/src/ui/mod.rs
@@ -230,7 +230,7 @@ pub fn file_picker(root: PathBuf, config: &helix_view::editor::Config) -> FilePi
cx.editor.set_error(err);
}
},
- |_editor, path| Some((path.clone(), None)),
+ |_editor, path| Some((path.clone().into(), None)),
)
}
diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs
index 54911924..5e9ca3d8 100644
--- a/helix-term/src/ui/picker.rs
+++ b/helix-term/src/ui/picker.rs
@@ -12,18 +12,14 @@ use fuzzy_matcher::skim::SkimMatcherV2 as Matcher;
use tui::widgets::Widget;
use std::{cmp::Ordering, time::Instant};
-use std::{
- collections::HashMap,
- io::Read,
- path::{Path, PathBuf},
-};
+use std::{collections::HashMap, io::Read, path::PathBuf};
use crate::ui::{Prompt, PromptEvent};
use helix_core::{movement::Direction, Position};
use helix_view::{
editor::Action,
graphics::{CursorKind, Margin, Modifier, Rect},
- Document, Editor,
+ Document, DocumentId, Editor,
};
use super::menu::Item;
@@ -32,8 +28,36 @@ pub const MIN_AREA_WIDTH_FOR_PREVIEW: u16 = 72;
/// Biggest file size to preview in bytes
pub const MAX_FILE_SIZE_FOR_PREVIEW: u64 = 10 * 1024 * 1024;
+#[derive(PartialEq, Eq, Hash)]
+pub enum PathOrId {
+ Id(DocumentId),
+ Path(PathBuf),
+}
+
+impl PathOrId {
+ fn get_canonicalized(self) -> std::io::Result<Self> {
+ use PathOrId::*;
+ Ok(match self {
+ Path(path) => Path(helix_core::path::get_canonicalized_path(&path)?),
+ Id(id) => Id(id),
+ })
+ }
+}
+
+impl From<PathBuf> for PathOrId {
+ fn from(v: PathBuf) -> Self {
+ Self::Path(v)
+ }
+}
+
+impl From<DocumentId> for PathOrId {
+ fn from(v: DocumentId) -> Self {
+ Self::Id(v)
+ }
+}
+
/// File path and range of lines (used to align and highlight lines)
-pub type FileLocation = (PathBuf, Option<(usize, usize)>);
+pub type FileLocation = (PathOrId, Option<(usize, usize)>);
pub struct FilePicker<T: Item> {
picker: Picker<T>,
@@ -112,62 +136,71 @@ impl<T: Item> FilePicker<T> {
self.picker
.selection()
.and_then(|current| (self.file_fn)(editor, current))
- .and_then(|(path, line)| {
- helix_core::path::get_canonicalized_path(&path)
- .ok()
- .zip(Some(line))
- })
+ .and_then(|(path_or_id, line)| path_or_id.get_canonicalized().ok().zip(Some(line)))
}
/// Get (cached) preview for a given path. If a document corresponding
/// to the path is already open in the editor, it is used instead.
fn get_preview<'picker, 'editor>(
&'picker mut self,
- path: &Path,
+ path_or_id: PathOrId,
editor: &'editor Editor,
) -> Preview<'picker, 'editor> {
- if let Some(doc) = editor.document_by_path(path) {
- return Preview::EditorDocument(doc);
- }
+ match path_or_id {
+ PathOrId::Path(path) => {
+ let path = &path;
+ if let Some(doc) = editor.document_by_path(path) {
+ return Preview::EditorDocument(doc);
+ }
- if self.preview_cache.contains_key(path) {
- return Preview::Cached(&self.preview_cache[path]);
- }
+ if self.preview_cache.contains_key(path) {
+ return Preview::Cached(&self.preview_cache[path]);
+ }
- let data = std::fs::File::open(path).and_then(|file| {
- let metadata = file.metadata()?;
- // Read up to 1kb to detect the content type
- let n = file.take(1024).read_to_end(&mut self.read_buffer)?;
- let content_type = content_inspector::inspect(&self.read_buffer[..n]);
- self.read_buffer.clear();
- Ok((metadata, content_type))
- });
- let preview = data
- .map(
- |(metadata, content_type)| match (metadata.len(), content_type) {
- (_, content_inspector::ContentType::BINARY) => CachedPreview::Binary,
- (size, _) if size > MAX_FILE_SIZE_FOR_PREVIEW => CachedPreview::LargeFile,
- _ => {
- // TODO: enable syntax highlighting; blocked by async rendering
- Document::open(path, None, None)
- .map(|doc| CachedPreview::Document(Box::new(doc)))
- .unwrap_or(CachedPreview::NotFound)
- }
- },
- )
- .unwrap_or(CachedPreview::NotFound);
- self.preview_cache.insert(path.to_owned(), preview);
- Preview::Cached(&self.preview_cache[path])
+ let data = std::fs::File::open(path).and_then(|file| {
+ let metadata = file.metadata()?;
+ // Read up to 1kb to detect the content type
+ let n = file.take(1024).read_to_end(&mut self.read_buffer)?;
+ let content_type = content_inspector::inspect(&self.read_buffer[..n]);
+ self.read_buffer.clear();
+ Ok((metadata, content_type))
+ });
+ let preview = data
+ .map(
+ |(metadata, content_type)| match (metadata.len(), content_type) {
+ (_, content_inspector::ContentType::BINARY) => CachedPreview::Binary,
+ (size, _) if size > MAX_FILE_SIZE_FOR_PREVIEW => {
+ CachedPreview::LargeFile
+ }
+ _ => {
+ // TODO: enable syntax highlighting; blocked by async rendering
+ Document::open(path, None, None)
+ .map(|doc| CachedPreview::Document(Box::new(doc)))
+ .unwrap_or(CachedPreview::NotFound)
+ }
+ },
+ )
+ .unwrap_or(CachedPreview::NotFound);
+ self.preview_cache.insert(path.to_owned(), preview);
+ Preview::Cached(&self.preview_cache[path])
+ }
+ PathOrId::Id(id) => {
+ let doc = editor.documents.get(&id).unwrap();
+ Preview::EditorDocument(doc)
+ }
+ }
}
fn handle_idle_timeout(&mut self, cx: &mut Context) -> EventResult {
// Try to find a document in the cache
let doc = self
.current_file(cx.editor)
- .and_then(|(path, _range)| self.preview_cache.get_mut(&path))
- .and_then(|cache| match cache {
- CachedPreview::Document(doc) => Some(doc),
- _ => None,
+ .and_then(|(path, _range)| match path {
+ PathOrId::Id(doc_id) => Some(doc_mut!(cx.editor, &doc_id)),
+ PathOrId::Path(path) => match self.preview_cache.get_mut(&path) {
+ Some(CachedPreview::Document(doc)) => Some(doc),
+ _ => None,
+ },
});
// Then attempt to highlight it if it has no language set
@@ -224,7 +257,7 @@ impl<T: Item + 'static> Component for FilePicker<T> {
block.render(preview_area, surface);
if let Some((path, range)) = self.current_file(cx.editor) {
- let preview = self.get_preview(&path, cx.editor);
+ let preview = self.get_preview(path, cx.editor);
let doc = match preview.document() {
Some(doc) => doc,
None => {