Start work on language docs
This commit is contained in:
@@ -42,7 +42,13 @@ use std::{
|
||||
};
|
||||
use sum_tree::TreeMap;
|
||||
use text::operation_queue::OperationQueue;
|
||||
pub use text::{Buffer as TextBuffer, BufferSnapshot as TextBufferSnapshot, *};
|
||||
use text::*;
|
||||
pub use text::{
|
||||
Anchor, Bias, Buffer as TextBuffer, BufferSnapshot as TextBufferSnapshot, Edit, OffsetRangeExt,
|
||||
OffsetUtf16, Patch, Point, PointUtf16, Rope, RopeFingerprint, Selection, SelectionGoal,
|
||||
Subscription, TextDimension, TextSummary, ToOffset, ToOffsetUtf16, ToPoint, ToPointUtf16,
|
||||
Transaction, TransactionId, Unclipped,
|
||||
};
|
||||
use theme::SyntaxTheme;
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
use util::RandomCharIter;
|
||||
@@ -63,6 +69,7 @@ pub enum Capability {
|
||||
ReadOnly,
|
||||
}
|
||||
|
||||
/// An in-memory representation of a source code file.
|
||||
pub struct Buffer {
|
||||
text: TextBuffer,
|
||||
diff_base: Option<String>,
|
||||
@@ -99,6 +106,8 @@ pub struct Buffer {
|
||||
capability: Capability,
|
||||
}
|
||||
|
||||
/// An immutable, cheaply cloneable representation of a certain
|
||||
/// state of a buffer.
|
||||
pub struct BufferSnapshot {
|
||||
text: text::BufferSnapshot,
|
||||
pub git_diff: git::diff::BufferDiff,
|
||||
@@ -150,6 +159,7 @@ pub struct GroupId {
|
||||
id: usize,
|
||||
}
|
||||
|
||||
/// A diagnostic associated with a certain range of a buffer.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Diagnostic {
|
||||
pub source: Option<String>,
|
||||
@@ -257,6 +267,7 @@ pub enum Event {
|
||||
Closed,
|
||||
}
|
||||
|
||||
/// The file associated with a buffer.
|
||||
pub trait File: Send + Sync {
|
||||
fn as_local(&self) -> Option<&dyn LocalFile>;
|
||||
|
||||
@@ -306,6 +317,10 @@ pub trait LocalFile: File {
|
||||
);
|
||||
}
|
||||
|
||||
/// The auto-indent behavior associated with an editing operation.
|
||||
/// For some editing operations, each affected line of text has its
|
||||
/// indentation recomputed. For other operations, the entire block
|
||||
/// of edited text is adjusted uniformly.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum AutoindentMode {
|
||||
/// Indent each line of inserted text.
|
||||
@@ -353,6 +368,8 @@ struct BufferChunkHighlights<'a> {
|
||||
highlight_maps: Vec<HighlightMap>,
|
||||
}
|
||||
|
||||
/// An iterator that yields chunks of a buffer's text, along with their
|
||||
/// syntax highlights and diagnostic status.
|
||||
pub struct BufferChunks<'a> {
|
||||
range: Range<usize>,
|
||||
chunks: text::Chunks<'a>,
|
||||
@@ -365,6 +382,8 @@ pub struct BufferChunks<'a> {
|
||||
highlights: Option<BufferChunkHighlights<'a>>,
|
||||
}
|
||||
|
||||
/// A chunk of a buffer's text, along with its syntax highlight and
|
||||
/// diagnostic status.
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct Chunk<'a> {
|
||||
pub text: &'a str,
|
||||
@@ -375,6 +394,7 @@ pub struct Chunk<'a> {
|
||||
pub is_tab: bool,
|
||||
}
|
||||
|
||||
/// A set of edits to a given version of a buffer, computed asynchronously.
|
||||
pub struct Diff {
|
||||
pub(crate) base_version: clock::Global,
|
||||
line_ending: LineEnding,
|
||||
@@ -407,6 +427,7 @@ impl CharKind {
|
||||
}
|
||||
|
||||
impl Buffer {
|
||||
/// Create a new buffer with the given base text.
|
||||
pub fn new<T: Into<String>>(replica_id: ReplicaId, id: u64, base_text: T) -> Self {
|
||||
Self::build(
|
||||
TextBuffer::new(replica_id, id, base_text.into()),
|
||||
@@ -416,6 +437,7 @@ impl Buffer {
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new buffer that is a replica of a remote buffer.
|
||||
pub fn remote(
|
||||
remote_id: u64,
|
||||
replica_id: ReplicaId,
|
||||
@@ -430,6 +452,8 @@ impl Buffer {
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new buffer that is a replica of a remote buffer, populating its
|
||||
/// state from the given protobuf message.
|
||||
pub fn from_proto(
|
||||
replica_id: ReplicaId,
|
||||
capability: Capability,
|
||||
@@ -456,6 +480,7 @@ impl Buffer {
|
||||
Ok(this)
|
||||
}
|
||||
|
||||
/// Serialize the buffer's state to a protobuf message.
|
||||
pub fn to_proto(&self) -> proto::BufferState {
|
||||
proto::BufferState {
|
||||
id: self.remote_id(),
|
||||
@@ -469,6 +494,7 @@ impl Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
/// Serialize as protobufs all of the changes to the buffer since the given version.
|
||||
pub fn serialize_ops(
|
||||
&self,
|
||||
since: Option<clock::Global>,
|
||||
@@ -515,6 +541,7 @@ impl Buffer {
|
||||
})
|
||||
}
|
||||
|
||||
/// Assign a language to the buffer, returning the buffer.
|
||||
pub fn with_language(mut self, language: Arc<Language>, cx: &mut ModelContext<Self>) -> Self {
|
||||
self.set_language(Some(language), cx);
|
||||
self
|
||||
@@ -572,6 +599,8 @@ impl Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieve a snapshot of the buffer's current state. This is computationally
|
||||
/// cheap, and allows reading from the buffer on a background thread.
|
||||
pub fn snapshot(&self) -> BufferSnapshot {
|
||||
let text = self.text.snapshot();
|
||||
let mut syntax_map = self.syntax_map.lock();
|
||||
@@ -594,18 +623,22 @@ impl Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_text_snapshot(&self) -> &text::BufferSnapshot {
|
||||
pub(crate) fn as_text_snapshot(&self) -> &text::BufferSnapshot {
|
||||
&self.text
|
||||
}
|
||||
|
||||
/// Retrieve a snapshot of the buffer's raw text, without any
|
||||
/// language-related state like the syntax tree or diagnostics.
|
||||
pub fn text_snapshot(&self) -> text::BufferSnapshot {
|
||||
self.text.snapshot()
|
||||
}
|
||||
|
||||
/// The file associated with the buffer, if any.
|
||||
pub fn file(&self) -> Option<&Arc<dyn File>> {
|
||||
self.file.as_ref()
|
||||
}
|
||||
|
||||
/// The version of the buffer that was last saved or reloaded from disk.
|
||||
pub fn saved_version(&self) -> &clock::Global {
|
||||
&self.saved_version
|
||||
}
|
||||
@@ -614,10 +647,12 @@ impl Buffer {
|
||||
self.file_fingerprint
|
||||
}
|
||||
|
||||
/// The mtime of the buffer's file when the buffer was last saved or reloaded from disk.
|
||||
pub fn saved_mtime(&self) -> SystemTime {
|
||||
self.saved_mtime
|
||||
}
|
||||
|
||||
/// Assign a language to the buffer.
|
||||
pub fn set_language(&mut self, language: Option<Arc<Language>>, cx: &mut ModelContext<Self>) {
|
||||
self.syntax_map.lock().clear();
|
||||
self.language = language;
|
||||
@@ -625,6 +660,8 @@ impl Buffer {
|
||||
cx.emit(Event::LanguageChanged);
|
||||
}
|
||||
|
||||
/// Assign a language registry to the buffer. This allows the buffer to retrieve
|
||||
/// other languages if parts of the buffer are written in different languages.
|
||||
pub fn set_language_registry(&mut self, language_registry: Arc<LanguageRegistry>) {
|
||||
self.syntax_map
|
||||
.lock()
|
||||
@@ -935,6 +972,7 @@ impl Buffer {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
/// Assign to the buffer a set of diagnostics created by a given language server.
|
||||
pub fn update_diagnostics(
|
||||
&mut self,
|
||||
server_id: LanguageServerId,
|
||||
@@ -1164,9 +1202,9 @@ impl Buffer {
|
||||
self.edit(edits, None, cx);
|
||||
}
|
||||
|
||||
// Create a minimal edit that will cause the the given row to be indented
|
||||
// with the given size. After applying this edit, the length of the line
|
||||
// will always be at least `new_size.len`.
|
||||
/// Create a minimal edit that will cause the the given row to be indented
|
||||
/// with the given size. After applying this edit, the length of the line
|
||||
/// will always be at least `new_size.len`.
|
||||
pub fn edit_for_indent_size_adjustment(
|
||||
row: u32,
|
||||
current_size: IndentSize,
|
||||
@@ -1201,6 +1239,8 @@ impl Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
/// Spawns a background task that asynchronously computes a `Diff` between the buffer's text
|
||||
/// and the given new text.
|
||||
pub fn diff(&self, mut new_text: String, cx: &AppContext) -> Task<Diff> {
|
||||
let old_text = self.as_rope().clone();
|
||||
let base_version = self.version();
|
||||
@@ -1272,7 +1312,7 @@ impl Buffer {
|
||||
})
|
||||
}
|
||||
|
||||
/// Spawn a background task that searches the buffer for any whitespace
|
||||
/// Spawns a background task that searches the buffer for any whitespace
|
||||
/// at the ends of a lines, and returns a `Diff` that removes that whitespace.
|
||||
pub fn remove_trailing_whitespace(&self, cx: &AppContext) -> Task<Diff> {
|
||||
let old_text = self.as_rope().clone();
|
||||
@@ -1292,7 +1332,7 @@ impl Buffer {
|
||||
})
|
||||
}
|
||||
|
||||
/// Ensure that the buffer ends with a single newline character, and
|
||||
/// Ensures that the buffer ends with a single newline character, and
|
||||
/// no other whitespace.
|
||||
pub fn ensure_final_newline(&mut self, cx: &mut ModelContext<Self>) {
|
||||
let len = self.len();
|
||||
@@ -1313,7 +1353,7 @@ impl Buffer {
|
||||
self.edit([(offset..len, "\n")], None, cx);
|
||||
}
|
||||
|
||||
/// Apply a diff to the buffer. If the buffer has changed since the given diff was
|
||||
/// Applies a diff to the buffer. If the buffer has changed since the given diff was
|
||||
/// calculated, then adjust the diff to account for those changes, and discard any
|
||||
/// parts of the diff that conflict with those changes.
|
||||
pub fn apply_diff(&mut self, diff: Diff, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
|
||||
@@ -1352,11 +1392,14 @@ impl Buffer {
|
||||
self.end_transaction(cx)
|
||||
}
|
||||
|
||||
/// Checks if the buffer has unsaved changes.
|
||||
pub fn is_dirty(&self) -> bool {
|
||||
self.file_fingerprint != self.as_rope().fingerprint()
|
||||
|| self.file.as_ref().map_or(false, |file| file.is_deleted())
|
||||
}
|
||||
|
||||
/// Checks if the buffer and its file have both changed since the buffer
|
||||
/// was last saved or reloaded.
|
||||
pub fn has_conflict(&self) -> bool {
|
||||
self.file_fingerprint != self.as_rope().fingerprint()
|
||||
&& self
|
||||
@@ -1365,14 +1408,23 @@ impl Buffer {
|
||||
.map_or(false, |file| file.mtime() > self.saved_mtime)
|
||||
}
|
||||
|
||||
/// Gets a [`Subscription`] that tracks all of the changes to the buffer's text.
|
||||
pub fn subscribe(&mut self) -> Subscription {
|
||||
self.text.subscribe()
|
||||
}
|
||||
|
||||
/// Starts a transaction, if one is not already in-progress. When undoing or
|
||||
/// redoing edits, all of the edits performed within a transaction are undone
|
||||
/// or redone together.
|
||||
pub fn start_transaction(&mut self) -> Option<TransactionId> {
|
||||
self.start_transaction_at(Instant::now())
|
||||
}
|
||||
|
||||
/// Starts a transaction, providing the current time. Subsequent transactions
|
||||
/// that occur within a short period of time will be grouped together. This
|
||||
/// is controlled by the buffer's undo grouping duration.
|
||||
///
|
||||
/// See [`Buffer::set_group_interval`].
|
||||
pub fn start_transaction_at(&mut self, now: Instant) -> Option<TransactionId> {
|
||||
self.transaction_depth += 1;
|
||||
if self.was_dirty_before_starting_transaction.is_none() {
|
||||
@@ -1381,10 +1433,16 @@ impl Buffer {
|
||||
self.text.start_transaction_at(now)
|
||||
}
|
||||
|
||||
/// Terminates the current transaction, if this is the outermost transaction.
|
||||
pub fn end_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
|
||||
self.end_transaction_at(Instant::now(), cx)
|
||||
}
|
||||
|
||||
/// Terminates the current transaction, providing the current time. Subsequent transactions
|
||||
/// that occur within a short period of time will be grouped together. This
|
||||
/// is controlled by the buffer's undo grouping duration.
|
||||
///
|
||||
/// See [`Buffer::set_group_interval`].
|
||||
pub fn end_transaction_at(
|
||||
&mut self,
|
||||
now: Instant,
|
||||
@@ -1405,26 +1463,33 @@ impl Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
/// Manually add a transaction to the buffer's undo history.
|
||||
pub fn push_transaction(&mut self, transaction: Transaction, now: Instant) {
|
||||
self.text.push_transaction(transaction, now);
|
||||
}
|
||||
|
||||
/// Prevent the last transaction from being grouped with any subsequent transactions,
|
||||
/// even if they occur with the buffer's undo grouping duration.
|
||||
pub fn finalize_last_transaction(&mut self) -> Option<&Transaction> {
|
||||
self.text.finalize_last_transaction()
|
||||
}
|
||||
|
||||
/// Manually group all changes since a given transaction.
|
||||
pub fn group_until_transaction(&mut self, transaction_id: TransactionId) {
|
||||
self.text.group_until_transaction(transaction_id);
|
||||
}
|
||||
|
||||
/// Manually remove a transaction from the buffer's undo history
|
||||
pub fn forget_transaction(&mut self, transaction_id: TransactionId) {
|
||||
self.text.forget_transaction(transaction_id);
|
||||
}
|
||||
|
||||
/// Manually merge two adjacent transactions in the buffer's undo history.
|
||||
pub fn merge_transactions(&mut self, transaction: TransactionId, destination: TransactionId) {
|
||||
self.text.merge_transactions(transaction, destination);
|
||||
}
|
||||
|
||||
/// Waits for the buffer to receive operations with the given timestamps.
|
||||
pub fn wait_for_edits(
|
||||
&mut self,
|
||||
edit_ids: impl IntoIterator<Item = clock::Lamport>,
|
||||
@@ -1432,6 +1497,7 @@ impl Buffer {
|
||||
self.text.wait_for_edits(edit_ids)
|
||||
}
|
||||
|
||||
/// Waits for the buffer to receive the operations necessary for resolving the given anchors.
|
||||
pub fn wait_for_anchors(
|
||||
&mut self,
|
||||
anchors: impl IntoIterator<Item = Anchor>,
|
||||
@@ -1439,14 +1505,18 @@ impl Buffer {
|
||||
self.text.wait_for_anchors(anchors)
|
||||
}
|
||||
|
||||
/// Waits for the buffer to receive operations up to the given version.
|
||||
pub fn wait_for_version(&mut self, version: clock::Global) -> impl Future<Output = Result<()>> {
|
||||
self.text.wait_for_version(version)
|
||||
}
|
||||
|
||||
/// Forces all futures returned by [`Buffer::wait_for_version`], [`Buffer::wait_for_edits`], or
|
||||
/// [`Buffer::wait_for_version`] to resolve with an error.
|
||||
pub fn give_up_waiting(&mut self) {
|
||||
self.text.give_up_waiting();
|
||||
}
|
||||
|
||||
/// Stores a set of selections that should be broadcasted to all of the buffer's replicas.
|
||||
pub fn set_active_selections(
|
||||
&mut self,
|
||||
selections: Arc<[Selection<Anchor>]>,
|
||||
@@ -1475,6 +1545,8 @@ impl Buffer {
|
||||
);
|
||||
}
|
||||
|
||||
/// Clears the selections, so that other replicas of the buffer do not see any selections for
|
||||
/// this replica.
|
||||
pub fn remove_active_selections(&mut self, cx: &mut ModelContext<Self>) {
|
||||
if self
|
||||
.remote_selections
|
||||
@@ -1485,6 +1557,7 @@ impl Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
/// Replaces the buffer's entire text.
|
||||
pub fn set_text<T>(&mut self, text: T, cx: &mut ModelContext<Self>) -> Option<clock::Lamport>
|
||||
where
|
||||
T: Into<Arc<str>>,
|
||||
@@ -1493,6 +1566,15 @@ impl Buffer {
|
||||
self.edit([(0..self.len(), text)], None, cx)
|
||||
}
|
||||
|
||||
/// Applies the given edits to the buffer. Each edit is specified as a range of text to
|
||||
/// delete, and a string of text to insert at that location.
|
||||
///
|
||||
/// If an [`AutoindentMode`] is provided, then the buffer will enqueue an auto-indent
|
||||
/// request for the edited ranges, which will be processed when the buffer finishes
|
||||
/// parsing.
|
||||
///
|
||||
/// Parsing takes place at the end of a transaction, and may compute synchronously
|
||||
/// or asynchronously, depending on the changes.
|
||||
pub fn edit<I, S, T>(
|
||||
&mut self,
|
||||
edits_iter: I,
|
||||
@@ -1626,6 +1708,7 @@ impl Buffer {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
/// Applies the given remote operations to the buffer.
|
||||
pub fn apply_ops<I: IntoIterator<Item = Operation>>(
|
||||
&mut self,
|
||||
ops: I,
|
||||
@@ -1773,11 +1856,13 @@ impl Buffer {
|
||||
cx.emit(Event::Operation(operation));
|
||||
}
|
||||
|
||||
/// Removes the selections for a given peer.
|
||||
pub fn remove_peer(&mut self, replica_id: ReplicaId, cx: &mut ModelContext<Self>) {
|
||||
self.remote_selections.remove(&replica_id);
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
/// Undoes the most recent transaction.
|
||||
pub fn undo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
|
||||
let was_dirty = self.is_dirty();
|
||||
let old_version = self.version.clone();
|
||||
@@ -1791,6 +1876,7 @@ impl Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
/// Manually undoes a specific transaction in the buffer's undo history.
|
||||
pub fn undo_transaction(
|
||||
&mut self,
|
||||
transaction_id: TransactionId,
|
||||
@@ -1807,6 +1893,7 @@ impl Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
/// Manually undoes all changes after a given transaction in the buffer's undo history.
|
||||
pub fn undo_to_transaction(
|
||||
&mut self,
|
||||
transaction_id: TransactionId,
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
//! The `language` crate provides... ???
|
||||
|
||||
#![warn(missing_docs)]
|
||||
|
||||
mod buffer;
|
||||
mod diagnostic_set;
|
||||
mod highlight_map;
|
||||
@@ -58,6 +62,9 @@ pub use syntax_map::{OwnedSyntaxLayerInfo, SyntaxLayerInfo};
|
||||
pub use text::LineEnding;
|
||||
pub use tree_sitter::{Parser, Tree};
|
||||
|
||||
/// Initializes the `language` crate.
|
||||
///
|
||||
/// This should be called before making use of items from the create.
|
||||
pub fn init(cx: &mut AppContext) {
|
||||
language_settings::init(cx);
|
||||
}
|
||||
@@ -90,7 +97,7 @@ thread_local! {
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref NEXT_GRAMMAR_ID: AtomicUsize = Default::default();
|
||||
pub(crate) static ref NEXT_GRAMMAR_ID: AtomicUsize = Default::default();
|
||||
pub static ref PLAIN_TEXT: Arc<Language> = Arc::new(Language::new(
|
||||
LanguageConfig {
|
||||
name: "Plain Text".into(),
|
||||
@@ -358,14 +365,22 @@ pub struct CodeLabel {
|
||||
|
||||
#[derive(Clone, Deserialize)]
|
||||
pub struct LanguageConfig {
|
||||
/// Human-readable name of the language.
|
||||
pub name: Arc<str>,
|
||||
// The name of the grammar in a WASM bundle.
|
||||
pub grammar_name: Option<Arc<str>>,
|
||||
/// Given a list of `LanguageConfig`'s, the language of a file can be determined based on the path extension matching any of the `path_suffixes`.
|
||||
pub path_suffixes: Vec<String>,
|
||||
/// List of
|
||||
pub brackets: BracketPairConfig,
|
||||
/// A regex pattern that determines whether the language should be assigned to a file or not.
|
||||
#[serde(default, deserialize_with = "deserialize_regex")]
|
||||
pub first_line_pattern: Option<Regex>,
|
||||
/// If set to true, auto indentation uses last non empty line to determine
|
||||
/// the indentation level for a new line.
|
||||
#[serde(default = "auto_indent_using_last_non_empty_line_default")]
|
||||
pub auto_indent_using_last_non_empty_line: bool,
|
||||
/// A regex that is used to determine whether the
|
||||
#[serde(default, deserialize_with = "deserialize_regex")]
|
||||
pub increase_indent_pattern: Option<Regex>,
|
||||
#[serde(default, deserialize_with = "deserialize_regex")]
|
||||
@@ -382,12 +397,16 @@ pub struct LanguageConfig {
|
||||
pub scope_opt_in_language_servers: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub overrides: HashMap<String, LanguageConfigOverride>,
|
||||
/// A list of characters that Zed should treat as word characters for the
|
||||
/// purpose of features that operate on word boundaries, like 'move to next word end'
|
||||
/// or a whole-word search in buffer search.
|
||||
#[serde(default)]
|
||||
pub word_characters: HashSet<char>,
|
||||
#[serde(default)]
|
||||
pub prettier_parser_name: Option<String>,
|
||||
}
|
||||
|
||||
/// Tree-sitter language queries for a given language.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct LanguageQueries {
|
||||
pub highlights: Option<Cow<'static, str>>,
|
||||
@@ -399,6 +418,9 @@ pub struct LanguageQueries {
|
||||
pub overrides: Option<Cow<'static, str>>,
|
||||
}
|
||||
|
||||
/// Represents a language for the given range. Some languages (e.g. HTML)
|
||||
/// interleave several languages together, thus a single buffer might actually contain
|
||||
/// several nested scopes.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct LanguageScope {
|
||||
language: Arc<Language>,
|
||||
@@ -491,7 +513,10 @@ pub struct FakeLspAdapter {
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct BracketPairConfig {
|
||||
/// A list of character pairs that should be treated as brackets in the context of a given language.
|
||||
pub pairs: Vec<BracketPair>,
|
||||
/// A list of tree-sitter scopes for which a given bracket should not be active.
|
||||
/// N-th entry in `[Self::disabled_scopes_by_bracket_ix]` contains a list of disabled scopes for an n-th entry in `[Self::pairs]`
|
||||
pub disabled_scopes_by_bracket_ix: Vec<Vec<String>>,
|
||||
}
|
||||
|
||||
@@ -1641,6 +1666,8 @@ impl LanguageScope {
|
||||
self.language.config.collapsed_placeholder.as_ref()
|
||||
}
|
||||
|
||||
/// Returns line prefix that is inserted in e.g. line continuations or
|
||||
/// in `toggle comments` action.
|
||||
pub fn line_comment_prefix(&self) -> Option<&Arc<str>> {
|
||||
Override::as_option(
|
||||
self.config_override().map(|o| &o.line_comment),
|
||||
@@ -1656,6 +1683,11 @@ impl LanguageScope {
|
||||
.map(|e| (&e.0, &e.1))
|
||||
}
|
||||
|
||||
/// Returns a list of language-specific word characters.
|
||||
///
|
||||
/// By default, Zed treats alphanumeric characters (and '_') as word characters for
|
||||
/// the purpose of actions like 'move to next word end` or whole-word search.
|
||||
/// It additionally accounts for language's additional word characters.
|
||||
pub fn word_characters(&self) -> Option<&HashSet<char>> {
|
||||
Override::as_option(
|
||||
self.config_override().map(|o| &o.word_characters),
|
||||
@@ -1663,6 +1695,8 @@ impl LanguageScope {
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns a list of bracket pairs for a given language with an additional
|
||||
/// piece of information about whether the particular bracket pair is currently active for a given language.
|
||||
pub fn brackets(&self) -> impl Iterator<Item = (&BracketPair, bool)> {
|
||||
let mut disabled_ids = self
|
||||
.config_override()
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//! Provides `language`-related settings.
|
||||
|
||||
use crate::{File, Language};
|
||||
use anyhow::Result;
|
||||
use collections::{HashMap, HashSet};
|
||||
@@ -11,10 +13,12 @@ use serde::{Deserialize, Serialize};
|
||||
use settings::Settings;
|
||||
use std::{num::NonZeroU32, path::Path, sync::Arc};
|
||||
|
||||
pub fn init(cx: &mut AppContext) {
|
||||
/// Initializes the language settings.
|
||||
pub(crate) fn init(cx: &mut AppContext) {
|
||||
AllLanguageSettings::register(cx);
|
||||
}
|
||||
|
||||
/// Returns the settings for the specified language from the provided file.
|
||||
pub fn language_settings<'a>(
|
||||
language: Option<&Arc<Language>>,
|
||||
file: Option<&Arc<dyn File>>,
|
||||
@@ -24,6 +28,7 @@ pub fn language_settings<'a>(
|
||||
all_language_settings(file, cx).language(language_name.as_deref())
|
||||
}
|
||||
|
||||
/// Returns the settings for all languages from the provided file.
|
||||
pub fn all_language_settings<'a>(
|
||||
file: Option<&Arc<dyn File>>,
|
||||
cx: &'a AppContext,
|
||||
@@ -32,36 +37,68 @@ pub fn all_language_settings<'a>(
|
||||
AllLanguageSettings::get(location, cx)
|
||||
}
|
||||
|
||||
/// The settings for all languages.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AllLanguageSettings {
|
||||
/// The settings for GitHub Copilot.
|
||||
pub copilot: CopilotSettings,
|
||||
defaults: LanguageSettings,
|
||||
languages: HashMap<Arc<str>, LanguageSettings>,
|
||||
}
|
||||
|
||||
/// The settings for a particular language.
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct LanguageSettings {
|
||||
/// How many columns a tab should occupy.
|
||||
pub tab_size: NonZeroU32,
|
||||
/// Whether to indent lines using tab characters, as opposed to multiple
|
||||
/// spaces.
|
||||
pub hard_tabs: bool,
|
||||
/// How to soft-wrap long lines of text.
|
||||
pub soft_wrap: SoftWrap,
|
||||
/// The column at which to soft-wrap lines, for buffers where soft-wrap
|
||||
/// is enabled.
|
||||
pub preferred_line_length: u32,
|
||||
/// Whether to show wrap guides in the editor. Setting this to true will
|
||||
/// show a guide at the 'preferred_line_length' value if softwrap is set to
|
||||
/// 'preferred_line_length', and will show any additional guides as specified
|
||||
/// by the 'wrap_guides' setting.
|
||||
pub show_wrap_guides: bool,
|
||||
/// Character counts at which to show wrap guides in the editor.
|
||||
pub wrap_guides: Vec<usize>,
|
||||
/// Whether or not to perform a buffer format before saving.
|
||||
pub format_on_save: FormatOnSave,
|
||||
/// Whether or not to remove any trailing whitespace from lines of a buffer
|
||||
/// before saving it.
|
||||
pub remove_trailing_whitespace_on_save: bool,
|
||||
/// Whether or not to ensure there's a single newline at the end of a buffer
|
||||
/// when saving it.
|
||||
pub ensure_final_newline_on_save: bool,
|
||||
/// How to perform a buffer format.
|
||||
pub formatter: Formatter,
|
||||
/// Zed's Prettier integration settings.
|
||||
/// If Prettier is enabled, Zed will use this its Prettier instance for any applicable file, if
|
||||
/// the project has no other Prettier installed.
|
||||
pub prettier: HashMap<String, serde_json::Value>,
|
||||
/// Whether to use language servers to provide code intelligence.
|
||||
pub enable_language_server: bool,
|
||||
/// Controls whether Copilot provides suggestion immediately (true)
|
||||
/// or waits for a `copilot::Toggle` (false).
|
||||
pub show_copilot_suggestions: bool,
|
||||
/// Whether to show tabs and spaces in the editor.
|
||||
pub show_whitespaces: ShowWhitespaceSetting,
|
||||
/// Whether to start a new line with a comment when a previous line is a comment as well.
|
||||
pub extend_comment_on_newline: bool,
|
||||
/// Inlay hint related settings.
|
||||
pub inlay_hints: InlayHintSettings,
|
||||
}
|
||||
|
||||
/// The settings for [GitHub Copilot](https://github.com/features/copilot).
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct CopilotSettings {
|
||||
/// Whether Copilit is enabled.
|
||||
pub feature_enabled: bool,
|
||||
/// A list of globs representing files that Copilot should be disabled for.
|
||||
pub disabled_globs: Vec<GlobMatcher>,
|
||||
}
|
||||
|
||||
@@ -138,7 +175,7 @@ pub struct LanguageSettingsContent {
|
||||
pub formatter: Option<Formatter>,
|
||||
/// Zed's Prettier integration settings.
|
||||
/// If Prettier is enabled, Zed will use this its Prettier instance for any applicable file, if
|
||||
/// project has no other Prettier installed.
|
||||
/// the project has no other Prettier installed.
|
||||
///
|
||||
/// Default: {}
|
||||
#[serde(default)]
|
||||
@@ -148,7 +185,7 @@ pub struct LanguageSettingsContent {
|
||||
/// Default: true
|
||||
#[serde(default)]
|
||||
pub enable_language_server: Option<bool>,
|
||||
/// Controls whether copilot provides suggestion immediately (true)
|
||||
/// Controls whether Copilot provides suggestion immediately (true)
|
||||
/// or waits for a `copilot::Toggle` (false).
|
||||
///
|
||||
/// Default: true
|
||||
@@ -176,9 +213,11 @@ pub struct CopilotSettingsContent {
|
||||
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub struct FeaturesContent {
|
||||
/// Whether the GitHub Copilot feature is enabled.
|
||||
pub copilot: Option<bool>,
|
||||
}
|
||||
|
||||
/// Controls the soft-wrapping behavior in the editor.
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum SoftWrap {
|
||||
@@ -190,14 +229,20 @@ pub enum SoftWrap {
|
||||
PreferredLineLength,
|
||||
}
|
||||
|
||||
/// Controls the behavior of formatting files when they are saved.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum FormatOnSave {
|
||||
/// Files should be formatted on save.
|
||||
On,
|
||||
/// Files should not be formatted on save.
|
||||
Off,
|
||||
LanguageServer,
|
||||
/// The external program to use to format the files on save.
|
||||
External {
|
||||
/// The external program to run.
|
||||
command: Arc<str>,
|
||||
/// The arguments to pass to the program.
|
||||
arguments: Arc<[String]>,
|
||||
},
|
||||
}
|
||||
@@ -231,6 +276,7 @@ pub enum Formatter {
|
||||
},
|
||||
}
|
||||
|
||||
/// The settings for inlay hints.
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
||||
pub struct InlayHintSettings {
|
||||
/// Global switch to toggle hints on and off.
|
||||
@@ -238,10 +284,19 @@ pub struct InlayHintSettings {
|
||||
/// Default: false
|
||||
#[serde(default)]
|
||||
pub enabled: bool,
|
||||
/// Whether type hints should be shown.
|
||||
///
|
||||
/// Default: true
|
||||
#[serde(default = "default_true")]
|
||||
pub show_type_hints: bool,
|
||||
/// Whether parameter hints should be shown.
|
||||
///
|
||||
/// Default: true
|
||||
#[serde(default = "default_true")]
|
||||
pub show_parameter_hints: bool,
|
||||
/// Whether other hints should be shown.
|
||||
///
|
||||
/// Default: true
|
||||
#[serde(default = "default_true")]
|
||||
pub show_other_hints: bool,
|
||||
}
|
||||
@@ -251,6 +306,7 @@ fn default_true() -> bool {
|
||||
}
|
||||
|
||||
impl InlayHintSettings {
|
||||
/// Returns the kinds of inlay hints that are enabled based on the settings.
|
||||
pub fn enabled_inlay_hint_kinds(&self) -> HashSet<Option<InlayHintKind>> {
|
||||
let mut kinds = HashSet::default();
|
||||
if self.show_type_hints {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//! Provides Markdown-related constructs.
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::{ops::Range, path::PathBuf};
|
||||
|
||||
@@ -5,21 +7,30 @@ use crate::{HighlightId, Language, LanguageRegistry};
|
||||
use gpui::{px, FontStyle, FontWeight, HighlightStyle, UnderlineStyle};
|
||||
use pulldown_cmark::{CodeBlockKind, Event, Options, Parser, Tag};
|
||||
|
||||
/// Parsed Markdown content.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ParsedMarkdown {
|
||||
/// The Markdown text.
|
||||
pub text: String,
|
||||
/// The list of highlights contained in the Markdown document.
|
||||
pub highlights: Vec<(Range<usize>, MarkdownHighlight)>,
|
||||
/// The regions of the various ranges in the Markdown document.
|
||||
pub region_ranges: Vec<Range<usize>>,
|
||||
/// The regions of the Markdown document.
|
||||
pub regions: Vec<ParsedRegion>,
|
||||
}
|
||||
|
||||
/// A run of highlighted Markdown text.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum MarkdownHighlight {
|
||||
/// A styled Markdown highlight.
|
||||
Style(MarkdownHighlightStyle),
|
||||
/// A highlighted code block.
|
||||
Code(HighlightId),
|
||||
}
|
||||
|
||||
impl MarkdownHighlight {
|
||||
/// Converts this [`MarkdownHighlight`] to a [`HighlightStyle`].
|
||||
pub fn to_highlight_style(&self, theme: &theme::SyntaxTheme) -> Option<HighlightStyle> {
|
||||
match self {
|
||||
MarkdownHighlight::Style(style) => {
|
||||
@@ -48,23 +59,39 @@ impl MarkdownHighlight {
|
||||
}
|
||||
}
|
||||
|
||||
/// The style for a Markdown highlight.
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq)]
|
||||
pub struct MarkdownHighlightStyle {
|
||||
/// Whether the text should be italicized.
|
||||
pub italic: bool,
|
||||
/// Whether the text should be underlined.
|
||||
pub underline: bool,
|
||||
/// The weight of the text.
|
||||
pub weight: FontWeight,
|
||||
}
|
||||
|
||||
/// A parsed region in a Markdown document.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ParsedRegion {
|
||||
/// Whether the region is a code block.
|
||||
pub code: bool,
|
||||
/// The link contained in this region, if it has one.
|
||||
pub link: Option<Link>,
|
||||
}
|
||||
|
||||
/// A Markdown link.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Link {
|
||||
Web { url: String },
|
||||
Path { path: PathBuf },
|
||||
/// A link to a webpage.
|
||||
Web {
|
||||
/// The URL of the webpage.
|
||||
url: String,
|
||||
},
|
||||
/// A link to a path on the filesystem.
|
||||
Path {
|
||||
/// The path to the item.
|
||||
path: PathBuf,
|
||||
},
|
||||
}
|
||||
|
||||
impl Link {
|
||||
@@ -82,6 +109,7 @@ impl Link {
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses a string of Markdown.
|
||||
pub async fn parse_markdown(
|
||||
markdown: &str,
|
||||
language_registry: &Arc<LanguageRegistry>,
|
||||
@@ -111,6 +139,7 @@ pub async fn parse_markdown(
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses a Markdown block.
|
||||
pub async fn parse_markdown_block(
|
||||
markdown: &str,
|
||||
language_registry: &Arc<LanguageRegistry>,
|
||||
@@ -261,6 +290,7 @@ pub async fn parse_markdown_block(
|
||||
}
|
||||
}
|
||||
|
||||
/// Appends a highlighted run of text to the provided `text` buffer.
|
||||
pub fn highlight_code(
|
||||
text: &mut String,
|
||||
highlights: &mut Vec<(Range<usize>, MarkdownHighlight)>,
|
||||
@@ -275,6 +305,7 @@ pub fn highlight_code(
|
||||
}
|
||||
}
|
||||
|
||||
/// Appends a new paragraph to the provided `text` buffer.
|
||||
pub fn new_paragraph(text: &mut String, list_stack: &mut Vec<(Option<u64>, bool)>) {
|
||||
let mut is_subsequent_paragraph_of_list = false;
|
||||
if let Some((_, has_content)) = list_stack.last_mut() {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//! Handles conversions of `language` items to and from the [`rpc`] protocol.
|
||||
|
||||
use crate::{
|
||||
diagnostic_set::DiagnosticEntry, CodeAction, CodeLabel, Completion, CursorShape, Diagnostic,
|
||||
Language,
|
||||
@@ -11,15 +13,18 @@ use text::*;
|
||||
|
||||
pub use proto::{BufferState, Operation};
|
||||
|
||||
/// Serializes a [`RopeFingerprint`] to be sent over the wire.
|
||||
pub fn serialize_fingerprint(fingerprint: RopeFingerprint) -> String {
|
||||
fingerprint.to_hex()
|
||||
}
|
||||
|
||||
/// Deserializes a [`RopeFingerprint`] from the wire format.
|
||||
pub fn deserialize_fingerprint(fingerprint: &str) -> Result<RopeFingerprint> {
|
||||
RopeFingerprint::from_hex(fingerprint)
|
||||
.map_err(|error| anyhow!("invalid fingerprint: {}", error))
|
||||
}
|
||||
|
||||
/// Deserializes a `[text::LineEnding]` from the wire format.
|
||||
pub fn deserialize_line_ending(message: proto::LineEnding) -> text::LineEnding {
|
||||
match message {
|
||||
proto::LineEnding::Unix => text::LineEnding::Unix,
|
||||
@@ -27,6 +32,7 @@ pub fn deserialize_line_ending(message: proto::LineEnding) -> text::LineEnding {
|
||||
}
|
||||
}
|
||||
|
||||
/// Serializes a [`text::LineEnding`] to be sent over the wire.
|
||||
pub fn serialize_line_ending(message: text::LineEnding) -> proto::LineEnding {
|
||||
match message {
|
||||
text::LineEnding::Unix => proto::LineEnding::Unix,
|
||||
@@ -34,6 +40,7 @@ pub fn serialize_line_ending(message: text::LineEnding) -> proto::LineEnding {
|
||||
}
|
||||
}
|
||||
|
||||
/// Serializes a [`crate::Operation`] to be sent over the wire.
|
||||
pub fn serialize_operation(operation: &crate::Operation) -> proto::Operation {
|
||||
proto::Operation {
|
||||
variant: Some(match operation {
|
||||
@@ -96,6 +103,7 @@ pub fn serialize_operation(operation: &crate::Operation) -> proto::Operation {
|
||||
}
|
||||
}
|
||||
|
||||
/// Serializes an [`operation::EditOperation`] to be sent over the wire.
|
||||
pub fn serialize_edit_operation(operation: &EditOperation) -> proto::operation::Edit {
|
||||
proto::operation::Edit {
|
||||
replica_id: operation.timestamp.replica_id as u32,
|
||||
@@ -110,6 +118,7 @@ pub fn serialize_edit_operation(operation: &EditOperation) -> proto::operation::
|
||||
}
|
||||
}
|
||||
|
||||
/// Serializes an entry in the undo map to be sent over the wire.
|
||||
pub fn serialize_undo_map_entry(
|
||||
(edit_id, counts): (&clock::Lamport, &[(clock::Lamport, u32)]),
|
||||
) -> proto::UndoMapEntry {
|
||||
|
||||
Reference in New Issue
Block a user