mirror of https://github.com/helix-editor/helix
core: Add a Uri variant for scratch buffers
parent
14a969e538
commit
a8d96db493
|
@ -1,18 +1,44 @@
|
|||
use std::{
|
||||
fmt,
|
||||
num::NonZeroUsize,
|
||||
path::{Path, PathBuf},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
// uses NonZeroUsize so Option<DocumentId> takes the same space
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub struct DocumentId(NonZeroUsize);
|
||||
|
||||
impl DocumentId {
|
||||
pub const MAX: Self = Self(unsafe { NonZeroUsize::new_unchecked(usize::MAX) });
|
||||
|
||||
pub fn next(&self) -> Self {
|
||||
// Safety: adding 1 from 1 is fine, probably impossible to reach usize max
|
||||
Self(unsafe { NonZeroUsize::new_unchecked(self.0.get() + 1) })
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for DocumentId {
|
||||
fn default() -> DocumentId {
|
||||
// Safety: 1 is non-zero
|
||||
DocumentId(unsafe { NonZeroUsize::new_unchecked(1) })
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for DocumentId {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// A generic pointer to a file location.
|
||||
///
|
||||
/// Currently this type only supports paths to local files.
|
||||
///
|
||||
/// Cloning this type is cheap: the internal representation uses an Arc.
|
||||
/// Cloning this type is cheap: the internal representation uses an Arc or data which is Copy.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[non_exhaustive]
|
||||
pub enum Uri {
|
||||
File(Arc<Path>),
|
||||
Scratch(DocumentId),
|
||||
}
|
||||
|
||||
impl Uri {
|
||||
|
@ -21,12 +47,14 @@ impl Uri {
|
|||
pub fn to_url(&self) -> Result<url::Url, ()> {
|
||||
match self {
|
||||
Uri::File(path) => url::Url::from_file_path(path),
|
||||
Uri::Scratch(_) => Err(()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_path(&self) -> Option<&Path> {
|
||||
match self {
|
||||
Self::File(path) => Some(path),
|
||||
Self::Scratch(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +69,7 @@ impl fmt::Display for Uri {
|
|||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::File(path) => write!(f, "{}", path.display()),
|
||||
Self::Scratch(id) => write!(f, "[scratch {id}]"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -335,9 +335,7 @@ pub fn symbol_picker(cx: &mut Context) {
|
|||
let request = language_server.document_symbols(doc.identifier()).unwrap();
|
||||
let offset_encoding = language_server.offset_encoding();
|
||||
let doc_id = doc.identifier();
|
||||
let doc_uri = doc
|
||||
.uri()
|
||||
.expect("docs with active language servers must be backed by paths");
|
||||
let doc_uri = doc.uri();
|
||||
|
||||
async move {
|
||||
let symbols = match request.await? {
|
||||
|
@ -555,11 +553,10 @@ pub fn workspace_symbol_picker(cx: &mut Context) {
|
|||
|
||||
pub fn diagnostics_picker(cx: &mut Context) {
|
||||
let doc = doc!(cx.editor);
|
||||
if let Some(uri) = doc.uri() {
|
||||
let diagnostics = cx.editor.diagnostics.get(&uri).cloned().unwrap_or_default();
|
||||
let picker = diag_picker(cx, [(uri, diagnostics)], DiagnosticsFormat::HideSourcePath);
|
||||
cx.push_layer(Box::new(overlaid(picker)));
|
||||
}
|
||||
let uri = doc.uri();
|
||||
let diagnostics = cx.editor.diagnostics.get(&uri).cloned().unwrap_or_default();
|
||||
let picker = diag_picker(cx, [(uri, diagnostics)], DiagnosticsFormat::HideSourcePath);
|
||||
cx.push_layer(Box::new(overlaid(picker)));
|
||||
}
|
||||
|
||||
pub fn workspace_diagnostics_picker(cx: &mut Context) {
|
||||
|
|
|
@ -1905,8 +1905,11 @@ impl Document {
|
|||
Url::from_file_path(self.path()?).ok()
|
||||
}
|
||||
|
||||
pub fn uri(&self) -> Option<helix_core::Uri> {
|
||||
Some(self.path()?.clone().into())
|
||||
pub fn uri(&self) -> helix_core::Uri {
|
||||
self.path
|
||||
.clone()
|
||||
.map(|path| path.into())
|
||||
.unwrap_or(helix_core::Uri::Scratch(self.id))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -29,7 +29,6 @@ use std::{
|
|||
collections::{BTreeMap, HashMap, HashSet},
|
||||
fs,
|
||||
io::{self, stdin},
|
||||
num::NonZeroUsize,
|
||||
path::{Path, PathBuf},
|
||||
pin::Pin,
|
||||
sync::Arc,
|
||||
|
@ -1711,9 +1710,7 @@ impl Editor {
|
|||
/// Generate an id for a new document and register it.
|
||||
fn new_document(&mut self, mut doc: Document) -> DocumentId {
|
||||
let id = self.next_document_id;
|
||||
// Safety: adding 1 from 1 is fine, probably impossible to reach usize max
|
||||
self.next_document_id =
|
||||
DocumentId(unsafe { NonZeroUsize::new_unchecked(self.next_document_id.0.get() + 1) });
|
||||
self.next_document_id = self.next_document_id.next();
|
||||
doc.id = id;
|
||||
self.documents.insert(id, doc);
|
||||
|
||||
|
@ -2031,9 +2028,8 @@ impl Editor {
|
|||
) -> impl Iterator<Item = helix_core::Diagnostic> + 'a {
|
||||
let text = document.text().clone();
|
||||
let language_config = document.language.clone();
|
||||
document
|
||||
.uri()
|
||||
.and_then(|uri| diagnostics.get(&uri))
|
||||
diagnostics
|
||||
.get(&document.uri())
|
||||
.map(|diags| {
|
||||
diags.iter().filter_map(move |(diagnostic, provider)| {
|
||||
let server_id = provider.language_server_id()?;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use std::cell::Cell;
|
||||
use std::num::NonZeroUsize;
|
||||
use std::sync::atomic::{self, AtomicUsize};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
@ -86,7 +85,7 @@ impl DiagnosticsHandler {
|
|||
active_generation,
|
||||
generation: Cell::new(0),
|
||||
events,
|
||||
last_doc: Cell::new(DocumentId(NonZeroUsize::new(usize::MAX).unwrap())),
|
||||
last_doc: Cell::new(DocumentId::MAX),
|
||||
last_cursor_line: Cell::new(usize::MAX),
|
||||
active: true,
|
||||
}
|
||||
|
|
|
@ -289,10 +289,7 @@ impl Editor {
|
|||
version: Option<i32>,
|
||||
mut diagnostics: Vec<lsp::Diagnostic>,
|
||||
) {
|
||||
let doc = self
|
||||
.documents
|
||||
.values_mut()
|
||||
.find(|doc| doc.uri().is_some_and(|u| u == uri));
|
||||
let doc = self.documents.values_mut().find(|doc| doc.uri() == uri);
|
||||
|
||||
if let Some((version, doc)) = version.zip(doc.as_ref()) {
|
||||
if version != doc.version() {
|
||||
|
|
|
@ -20,25 +20,6 @@ pub mod theme;
|
|||
pub mod tree;
|
||||
pub mod view;
|
||||
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
// uses NonZeroUsize so Option<DocumentId> use a byte rather than two
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub struct DocumentId(NonZeroUsize);
|
||||
|
||||
impl Default for DocumentId {
|
||||
fn default() -> DocumentId {
|
||||
// Safety: 1 is non-zero
|
||||
DocumentId(unsafe { NonZeroUsize::new_unchecked(1) })
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for DocumentId {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_fmt(format_args!("{}", self.0))
|
||||
}
|
||||
}
|
||||
|
||||
slotmap::new_key_type! {
|
||||
pub struct ViewId;
|
||||
}
|
||||
|
@ -78,5 +59,6 @@ pub use action::Action;
|
|||
pub use document::Document;
|
||||
pub use editor::Editor;
|
||||
use helix_core::char_idx_at_visual_offset;
|
||||
pub use helix_core::uri::DocumentId;
|
||||
pub use theme::Theme;
|
||||
pub use view::View;
|
||||
|
|
Loading…
Reference in New Issue