forked from Mirrors/helix
Merge branch 'master'
commit
e20886dd60
@ -0,0 +1,139 @@
|
|||||||
|
name: Build
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
schedule:
|
||||||
|
- cron: '00 01 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check:
|
||||||
|
name: Check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
rust: [stable, msrv]
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Use MSRV rust toolchain
|
||||||
|
if: matrix.rust == 'msrv'
|
||||||
|
run: cp .github/workflows/msrv-rust-toolchain.toml rust-toolchain.toml
|
||||||
|
|
||||||
|
- name: Install stable toolchain
|
||||||
|
uses: helix-editor/rust-toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- uses: Swatinem/rust-cache@v2
|
||||||
|
|
||||||
|
- name: Run cargo check
|
||||||
|
run: cargo check
|
||||||
|
|
||||||
|
test:
|
||||||
|
name: Test Suite
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
env:
|
||||||
|
RUST_BACKTRACE: 1
|
||||||
|
HELIX_LOG_LEVEL: info
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install stable toolchain
|
||||||
|
uses: helix-editor/rust-toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- uses: Swatinem/rust-cache@v2
|
||||||
|
|
||||||
|
- name: Cache test tree-sitter grammar
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: runtime/grammars
|
||||||
|
key: ${{ runner.os }}-stable-v${{ env.CACHE_VERSION }}-tree-sitter-grammars-${{ hashFiles('languages.toml') }}
|
||||||
|
restore-keys: ${{ runner.os }}-stable-v${{ env.CACHE_VERSION }}-tree-sitter-grammars-
|
||||||
|
|
||||||
|
- name: Run cargo test
|
||||||
|
run: cargo test --workspace
|
||||||
|
|
||||||
|
- name: Run cargo integration-test
|
||||||
|
run: cargo integration-test
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||||
|
|
||||||
|
lints:
|
||||||
|
name: Lints
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install stable toolchain
|
||||||
|
uses: helix-editor/rust-toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
override: true
|
||||||
|
components: rustfmt, clippy
|
||||||
|
|
||||||
|
- uses: Swatinem/rust-cache@v2
|
||||||
|
|
||||||
|
- name: Run cargo fmt
|
||||||
|
run: cargo fmt --all -- --check
|
||||||
|
|
||||||
|
- name: Run cargo clippy
|
||||||
|
run: cargo clippy --workspace --all-targets -- -D warnings
|
||||||
|
|
||||||
|
- name: Run cargo doc
|
||||||
|
run: cargo doc --no-deps --workspace --document-private-items
|
||||||
|
env:
|
||||||
|
RUSTDOCFLAGS: -D warnings
|
||||||
|
|
||||||
|
docs:
|
||||||
|
name: Docs
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install stable toolchain
|
||||||
|
uses: helix-editor/rust-toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- uses: Swatinem/rust-cache@v2
|
||||||
|
|
||||||
|
- name: Generate docs
|
||||||
|
run: cargo xtask docgen
|
||||||
|
|
||||||
|
- name: Check uncommitted documentation changes
|
||||||
|
run: |
|
||||||
|
git diff
|
||||||
|
git diff-files --quiet \
|
||||||
|
|| (echo "Run 'cargo xtask docgen', commit the changes and push again" \
|
||||||
|
&& exit 1)
|
||||||
|
|
||||||
|
queries:
|
||||||
|
name: Tree-sitter queries
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install stable toolchain
|
||||||
|
uses: helix-editor/rust-toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- uses: Swatinem/rust-cache@v2
|
||||||
|
|
||||||
|
- name: Generate docs
|
||||||
|
run: cargo xtask query-check
|
@ -0,0 +1,139 @@
|
|||||||
|
name: Build
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
schedule:
|
||||||
|
- cron: '00 01 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check:
|
||||||
|
name: Check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
rust: [stable, msrv]
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Use MSRV rust toolchain
|
||||||
|
if: matrix.rust == 'msrv'
|
||||||
|
run: cp .github/workflows/msrv-rust-toolchain.toml rust-toolchain.toml
|
||||||
|
|
||||||
|
- name: Install stable toolchain
|
||||||
|
uses: helix-editor/rust-toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- uses: Swatinem/rust-cache@v2
|
||||||
|
|
||||||
|
- name: Run cargo check
|
||||||
|
run: cargo check
|
||||||
|
|
||||||
|
test:
|
||||||
|
name: Test Suite
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
env:
|
||||||
|
RUST_BACKTRACE: 1
|
||||||
|
HELIX_LOG_LEVEL: info
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install stable toolchain
|
||||||
|
uses: helix-editor/rust-toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- uses: Swatinem/rust-cache@v2
|
||||||
|
|
||||||
|
- name: Cache test tree-sitter grammar
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: runtime/grammars
|
||||||
|
key: ${{ runner.os }}-stable-v${{ env.CACHE_VERSION }}-tree-sitter-grammars-${{ hashFiles('languages.toml') }}
|
||||||
|
restore-keys: ${{ runner.os }}-stable-v${{ env.CACHE_VERSION }}-tree-sitter-grammars-
|
||||||
|
|
||||||
|
- name: Run cargo test
|
||||||
|
run: cargo test --workspace
|
||||||
|
|
||||||
|
- name: Run cargo integration-test
|
||||||
|
run: cargo integration-test
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||||
|
|
||||||
|
lints:
|
||||||
|
name: Lints
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install stable toolchain
|
||||||
|
uses: helix-editor/rust-toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
override: true
|
||||||
|
components: rustfmt, clippy
|
||||||
|
|
||||||
|
- uses: Swatinem/rust-cache@v2
|
||||||
|
|
||||||
|
- name: Run cargo fmt
|
||||||
|
run: cargo fmt --all -- --check
|
||||||
|
|
||||||
|
- name: Run cargo clippy
|
||||||
|
run: cargo clippy --workspace --all-targets -- -D warnings
|
||||||
|
|
||||||
|
- name: Run cargo doc
|
||||||
|
run: cargo doc --no-deps --workspace --document-private-items
|
||||||
|
env:
|
||||||
|
RUSTDOCFLAGS: -D warnings
|
||||||
|
|
||||||
|
docs:
|
||||||
|
name: Docs
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install stable toolchain
|
||||||
|
uses: helix-editor/rust-toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- uses: Swatinem/rust-cache@v2
|
||||||
|
|
||||||
|
- name: Generate docs
|
||||||
|
run: cargo xtask docgen
|
||||||
|
|
||||||
|
- name: Check uncommitted documentation changes
|
||||||
|
run: |
|
||||||
|
git diff
|
||||||
|
git diff-files --quiet \
|
||||||
|
|| (echo "Run 'cargo xtask docgen', commit the changes and push again" \
|
||||||
|
&& exit 1)
|
||||||
|
|
||||||
|
queries:
|
||||||
|
name: Tree-sitter queries
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install stable toolchain
|
||||||
|
uses: helix-editor/rust-toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- uses: Swatinem/rust-cache@v2
|
||||||
|
|
||||||
|
- name: Generate docs
|
||||||
|
run: cargo xtask query-check
|
@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="CPP_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
|
</profile>
|
||||||
|
</component>
|
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/helix.iml" filepath="$PROJECT_DIR$/.idea/helix.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -1,17 +0,0 @@
|
|||||||
use crate::{Rope, Selection};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct State {
|
|
||||||
pub doc: Rope,
|
|
||||||
pub selection: Selection,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl State {
|
|
||||||
#[must_use]
|
|
||||||
pub fn new(doc: Rope) -> Self {
|
|
||||||
Self {
|
|
||||||
doc,
|
|
||||||
selection: Selection::point(0),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,696 @@
|
|||||||
|
mod client;
|
||||||
|
pub mod jsonrpc;
|
||||||
|
mod transport;
|
||||||
|
|
||||||
|
pub use client::Client;
|
||||||
|
pub use futures_executor::block_on;
|
||||||
|
pub use jsonrpc::Call;
|
||||||
|
pub use lsp::{Position, Url};
|
||||||
|
pub use lsp_types as lsp;
|
||||||
|
|
||||||
|
use futures_util::stream::select_all::SelectAll;
|
||||||
|
use helix_core::syntax::{LanguageConfiguration, LanguageServerConfiguration};
|
||||||
|
use tokio::sync::mpsc::UnboundedReceiver;
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
collections::{hash_map::Entry, HashMap},
|
||||||
|
path::PathBuf,
|
||||||
|
sync::{
|
||||||
|
atomic::{AtomicUsize, Ordering},
|
||||||
|
Arc,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use thiserror::Error;
|
||||||
|
use tokio_stream::wrappers::UnboundedReceiverStream;
|
||||||
|
|
||||||
|
pub type Result<T> = core::result::Result<T, Error>;
|
||||||
|
type LanguageId = String;
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
#[error("protocol error: {0}")]
|
||||||
|
Rpc(#[from] jsonrpc::Error),
|
||||||
|
#[error("failed to parse: {0}")]
|
||||||
|
Parse(#[from] serde_json::Error),
|
||||||
|
#[error("IO Error: {0}")]
|
||||||
|
IO(#[from] std::io::Error),
|
||||||
|
#[error("request timed out")]
|
||||||
|
Timeout,
|
||||||
|
#[error("server closed the stream")]
|
||||||
|
StreamClosed,
|
||||||
|
#[error("LPS not defined")]
|
||||||
|
LspNotDefined,
|
||||||
|
#[error("Unhandled")]
|
||||||
|
Unhandled,
|
||||||
|
#[error(transparent)]
|
||||||
|
Other(#[from] anyhow::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||||
|
pub enum OffsetEncoding {
|
||||||
|
/// UTF-8 code units aka bytes
|
||||||
|
#[serde(rename = "utf-8")]
|
||||||
|
Utf8,
|
||||||
|
/// UTF-16 code units
|
||||||
|
#[serde(rename = "utf-16")]
|
||||||
|
Utf16,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod util {
|
||||||
|
use super::*;
|
||||||
|
use helix_core::{diagnostic::NumberOrString, Range, Rope, Transaction};
|
||||||
|
|
||||||
|
/// Converts a diagnostic in the document to [`lsp::Diagnostic`].
|
||||||
|
///
|
||||||
|
/// Panics when [`pos_to_lsp_pos`] would for an invalid range on the diagnostic.
|
||||||
|
pub fn diagnostic_to_lsp_diagnostic(
|
||||||
|
doc: &Rope,
|
||||||
|
diag: &helix_core::diagnostic::Diagnostic,
|
||||||
|
offset_encoding: OffsetEncoding,
|
||||||
|
) -> lsp::Diagnostic {
|
||||||
|
use helix_core::diagnostic::Severity::*;
|
||||||
|
|
||||||
|
let range = Range::new(diag.range.start, diag.range.end);
|
||||||
|
let severity = diag.severity.map(|s| match s {
|
||||||
|
Hint => lsp::DiagnosticSeverity::HINT,
|
||||||
|
Info => lsp::DiagnosticSeverity::INFORMATION,
|
||||||
|
Warning => lsp::DiagnosticSeverity::WARNING,
|
||||||
|
Error => lsp::DiagnosticSeverity::ERROR,
|
||||||
|
});
|
||||||
|
|
||||||
|
let code = match diag.code.clone() {
|
||||||
|
Some(x) => match x {
|
||||||
|
NumberOrString::Number(x) => Some(lsp::NumberOrString::Number(x)),
|
||||||
|
NumberOrString::String(x) => Some(lsp::NumberOrString::String(x)),
|
||||||
|
},
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let new_tags: Vec<_> = diag
|
||||||
|
.tags
|
||||||
|
.iter()
|
||||||
|
.map(|tag| match tag {
|
||||||
|
helix_core::diagnostic::DiagnosticTag::Unnecessary => {
|
||||||
|
lsp::DiagnosticTag::UNNECESSARY
|
||||||
|
}
|
||||||
|
helix_core::diagnostic::DiagnosticTag::Deprecated => lsp::DiagnosticTag::DEPRECATED,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let tags = if !new_tags.is_empty() {
|
||||||
|
Some(new_tags)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: add support for Diagnostic.data
|
||||||
|
lsp::Diagnostic::new(
|
||||||
|
range_to_lsp_range(doc, range, offset_encoding),
|
||||||
|
severity,
|
||||||
|
code,
|
||||||
|
diag.source.clone(),
|
||||||
|
diag.message.to_owned(),
|
||||||
|
None,
|
||||||
|
tags,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts [`lsp::Position`] to a position in the document.
|
||||||
|
///
|
||||||
|
/// Returns `None` if position exceeds document length or an operation overflows.
|
||||||
|
pub fn lsp_pos_to_pos(
|
||||||
|
doc: &Rope,
|
||||||
|
pos: lsp::Position,
|
||||||
|
offset_encoding: OffsetEncoding,
|
||||||
|
) -> Option<usize> {
|
||||||
|
let pos_line = pos.line as usize;
|
||||||
|
if pos_line > doc.len_lines() - 1 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
match offset_encoding {
|
||||||
|
OffsetEncoding::Utf8 => {
|
||||||
|
let line = doc.line_to_char(pos_line);
|
||||||
|
let pos = line.checked_add(pos.character as usize)?;
|
||||||
|
if pos <= doc.len_chars() {
|
||||||
|
Some(pos)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OffsetEncoding::Utf16 => {
|
||||||
|
let line = doc.line_to_char(pos_line);
|
||||||
|
let line_start = doc.char_to_utf16_cu(line);
|
||||||
|
let pos = line_start.checked_add(pos.character as usize)?;
|
||||||
|
doc.try_utf16_cu_to_char(pos).ok()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts position in the document to [`lsp::Position`].
|
||||||
|
///
|
||||||
|
/// Panics when `pos` is out of `doc` bounds or operation overflows.
|
||||||
|
pub fn pos_to_lsp_pos(
|
||||||
|
doc: &Rope,
|
||||||
|
pos: usize,
|
||||||
|
offset_encoding: OffsetEncoding,
|
||||||
|
) -> lsp::Position {
|
||||||
|
match offset_encoding {
|
||||||
|
OffsetEncoding::Utf8 => {
|
||||||
|
let line = doc.char_to_line(pos);
|
||||||
|
let line_start = doc.line_to_char(line);
|
||||||
|
let col = pos - line_start;
|
||||||
|
|
||||||
|
lsp::Position::new(line as u32, col as u32)
|
||||||
|
}
|
||||||
|
OffsetEncoding::Utf16 => {
|
||||||
|
let line = doc.char_to_line(pos);
|
||||||
|
let line_start = doc.char_to_utf16_cu(doc.line_to_char(line));
|
||||||
|
let col = doc.char_to_utf16_cu(pos) - line_start;
|
||||||
|
|
||||||
|
lsp::Position::new(line as u32, col as u32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts a range in the document to [`lsp::Range`].
|
||||||
|
pub fn range_to_lsp_range(
|
||||||
|
doc: &Rope,
|
||||||
|
range: Range,
|
||||||
|
offset_encoding: OffsetEncoding,
|
||||||
|
) -> lsp::Range {
|
||||||
|
let start = pos_to_lsp_pos(doc, range.from(), offset_encoding);
|
||||||
|
let end = pos_to_lsp_pos(doc, range.to(), offset_encoding);
|
||||||
|
|
||||||
|
lsp::Range::new(start, end)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lsp_range_to_range(
|
||||||
|
doc: &Rope,
|
||||||
|
range: lsp::Range,
|
||||||
|
offset_encoding: OffsetEncoding,
|
||||||
|
) -> Option<Range> {
|
||||||
|
let start = lsp_pos_to_pos(doc, range.start, offset_encoding)?;
|
||||||
|
let end = lsp_pos_to_pos(doc, range.end, offset_encoding)?;
|
||||||
|
|
||||||
|
Some(Range::new(start, end))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_transaction_from_edits(
|
||||||
|
doc: &Rope,
|
||||||
|
mut edits: Vec<lsp::TextEdit>,
|
||||||
|
offset_encoding: OffsetEncoding,
|
||||||
|
) -> Transaction {
|
||||||
|
// Sort edits by start range, since some LSPs (Omnisharp) send them
|
||||||
|
// in reverse order.
|
||||||
|
edits.sort_unstable_by_key(|edit| edit.range.start);
|
||||||
|
|
||||||
|
// Generate a diff if the edit is a full document replacement.
|
||||||
|
#[allow(clippy::collapsible_if)]
|
||||||
|
if edits.len() == 1 {
|
||||||
|
let is_document_replacement = edits.first().and_then(|edit| {
|
||||||
|
let start = lsp_pos_to_pos(doc, edit.range.start, offset_encoding)?;
|
||||||
|
let end = lsp_pos_to_pos(doc, edit.range.end, offset_encoding)?;
|
||||||
|
Some(start..end)
|
||||||
|
}) == Some(0..doc.len_chars());
|
||||||
|
if is_document_replacement {
|
||||||
|
let new_text = Rope::from(edits.pop().unwrap().new_text);
|
||||||
|
return helix_core::diff::compare_ropes(doc, &new_text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Transaction::change(
|
||||||
|
doc,
|
||||||
|
edits.into_iter().map(|edit| {
|
||||||
|
// simplify "" into None for cleaner changesets
|
||||||
|
let replacement = if !edit.new_text.is_empty() {
|
||||||
|
Some(edit.new_text.into())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let start =
|
||||||
|
if let Some(start) = lsp_pos_to_pos(doc, edit.range.start, offset_encoding) {
|
||||||
|
start
|
||||||
|
} else {
|
||||||
|
return (0, 0, None);
|
||||||
|
};
|
||||||
|
let end = if let Some(end) = lsp_pos_to_pos(doc, edit.range.end, offset_encoding) {
|
||||||
|
end
|
||||||
|
} else {
|
||||||
|
return (0, 0, None);
|
||||||
|
};
|
||||||
|
(start, end, replacement)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub enum MethodCall {
|
||||||
|
WorkDoneProgressCreate(lsp::WorkDoneProgressCreateParams),
|
||||||
|
ApplyWorkspaceEdit(lsp::ApplyWorkspaceEditParams),
|
||||||
|
WorkspaceFolders,
|
||||||
|
WorkspaceConfiguration(lsp::ConfigurationParams),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MethodCall {
|
||||||
|
pub fn parse(method: &str, params: jsonrpc::Params) -> Result<MethodCall> {
|
||||||
|
use lsp::request::Request;
|
||||||
|
let request = match method {
|
||||||
|
lsp::request::WorkDoneProgressCreate::METHOD => {
|
||||||
|
let params: lsp::WorkDoneProgressCreateParams = params.parse()?;
|
||||||
|
Self::WorkDoneProgressCreate(params)
|
||||||
|
}
|
||||||
|
lsp::request::ApplyWorkspaceEdit::METHOD => {
|
||||||
|
let params: lsp::ApplyWorkspaceEditParams = params.parse()?;
|
||||||
|
Self::ApplyWorkspaceEdit(params)
|
||||||
|
}
|
||||||
|
lsp::request::WorkspaceFoldersRequest::METHOD => Self::WorkspaceFolders,
|
||||||
|
lsp::request::WorkspaceConfiguration::METHOD => {
|
||||||
|
let params: lsp::ConfigurationParams = params.parse()?;
|
||||||
|
Self::WorkspaceConfiguration(params)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(Error::Unhandled);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(request)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub enum Notification {
|
||||||
|
// we inject this notification to signal the LSP is ready
|
||||||
|
Initialized,
|
||||||
|
// and this notification to signal that the LSP exited
|
||||||
|
Exit,
|
||||||
|
PublishDiagnostics(lsp::PublishDiagnosticsParams),
|
||||||
|
ShowMessage(lsp::ShowMessageParams),
|
||||||
|
LogMessage(lsp::LogMessageParams),
|
||||||
|
ProgressMessage(lsp::ProgressParams),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Notification {
|
||||||
|
pub fn parse(method: &str, params: jsonrpc::Params) -> Result<Notification> {
|
||||||
|
use lsp::notification::Notification as _;
|
||||||
|
|
||||||
|
let notification = match method {
|
||||||
|
lsp::notification::Initialized::METHOD => Self::Initialized,
|
||||||
|
lsp::notification::Exit::METHOD => Self::Exit,
|
||||||
|
lsp::notification::PublishDiagnostics::METHOD => {
|
||||||
|
let params: lsp::PublishDiagnosticsParams = params.parse()?;
|
||||||
|
Self::PublishDiagnostics(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
lsp::notification::ShowMessage::METHOD => {
|
||||||
|
let params: lsp::ShowMessageParams = params.parse()?;
|
||||||
|
Self::ShowMessage(params)
|
||||||
|
}
|
||||||
|
lsp::notification::LogMessage::METHOD => {
|
||||||
|
let params: lsp::LogMessageParams = params.parse()?;
|
||||||
|
Self::LogMessage(params)
|
||||||
|
}
|
||||||
|
lsp::notification::Progress::METHOD => {
|
||||||
|
let params: lsp::ProgressParams = params.parse()?;
|
||||||
|
Self::ProgressMessage(params)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(Error::Unhandled);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(notification)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Registry {
|
||||||
|
inner: HashMap<LanguageId, (usize, Arc<Client>)>,
|
||||||
|
|
||||||
|
counter: AtomicUsize,
|
||||||
|
pub incoming: SelectAll<UnboundedReceiverStream<(usize, Call)>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Registry {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Registry {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
inner: HashMap::new(),
|
||||||
|
counter: AtomicUsize::new(0),
|
||||||
|
incoming: SelectAll::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_by_id(&self, id: usize) -> Option<&Client> {
|
||||||
|
self.inner
|
||||||
|
.values()
|
||||||
|
.find(|(client_id, _)| client_id == &id)
|
||||||
|
.map(|(_, client)| client.as_ref())
|
||||||
|
}
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
||||||| 4ec2a21c
|
||||||
|
pub fn restart(
|
||||||
|
&mut self,
|
||||||
|
language_config: &LanguageConfiguration,
|
||||||
|
doc_path: Option<&std::path::PathBuf>,
|
||||||
|
) -> Result<Option<Arc<Client>>> {
|
||||||
|
let config = match &language_config.language_server {
|
||||||
|
Some(config) => config,
|
||||||
|
None => return Ok(None),
|
||||||
|
};
|
||||||
|
|
||||||
|
let scope = language_config.scope.clone();
|
||||||
|
|
||||||
|
match self.inner.entry(scope) {
|
||||||
|
Entry::Vacant(_) => Ok(None),
|
||||||
|
Entry::Occupied(mut entry) => {
|
||||||
|
// initialize a new client
|
||||||
|
let id = self.counter.fetch_add(1, Ordering::Relaxed);
|
||||||
|
|
||||||
|
let NewClientResult(client, incoming) =
|
||||||
|
start_client(id, language_config, config, doc_path)?;
|
||||||
|
self.incoming.push(UnboundedReceiverStream::new(incoming));
|
||||||
|
|
||||||
|
let (_, old_client) = entry.insert((id, client.clone()));
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let _ = old_client.force_shutdown().await;
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(Some(client))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
=======
|
||||||
|
pub fn remove_by_id(&mut self, id: usize) {
|
||||||
|
self.inner.retain(|_, (client_id, _)| client_id != &id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn restart(
|
||||||
|
&mut self,
|
||||||
|
language_config: &LanguageConfiguration,
|
||||||
|
doc_path: Option<&std::path::PathBuf>,
|
||||||
|
) -> Result<Option<Arc<Client>>> {
|
||||||
|
let config = match &language_config.language_server {
|
||||||
|
Some(config) => config,
|
||||||
|
None => return Ok(None),
|
||||||
|
};
|
||||||
|
|
||||||
|
let scope = language_config.scope.clone();
|
||||||
|
|
||||||
|
match self.inner.entry(scope) {
|
||||||
|
Entry::Vacant(_) => Ok(None),
|
||||||
|
Entry::Occupied(mut entry) => {
|
||||||
|
// initialize a new client
|
||||||
|
let id = self.counter.fetch_add(1, Ordering::Relaxed);
|
||||||
|
|
||||||
|
let NewClientResult(client, incoming) =
|
||||||
|
start_client(id, language_config, config, doc_path)?;
|
||||||
|
self.incoming.push(UnboundedReceiverStream::new(incoming));
|
||||||
|
|
||||||
|
let (_, old_client) = entry.insert((id, client.clone()));
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let _ = old_client.force_shutdown().await;
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(Some(client))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
>>>>>>> master
|
||||||
|
pub fn get(
|
||||||
|
&mut self,
|
||||||
|
language_config: &LanguageConfiguration,
|
||||||
|
doc_path: Option<&std::path::PathBuf>,
|
||||||
|
) -> Result<Option<Arc<Client>>> {
|
||||||
|
let config = match &language_config.language_server {
|
||||||
|
Some(config) => config,
|
||||||
|
None => return Ok(None),
|
||||||
|
};
|
||||||
|
|
||||||
|
match self.inner.entry(language_config.scope.clone()) {
|
||||||
|
Entry::Occupied(entry) => Ok(Some(entry.get().1.clone())),
|
||||||
|
Entry::Vacant(entry) => {
|
||||||
|
// initialize a new client
|
||||||
|
let id = self.counter.fetch_add(1, Ordering::Relaxed);
|
||||||
|
|
||||||
|
let NewClientResult(client, incoming) =
|
||||||
|
start_client(id, language_config, config, doc_path)?;
|
||||||
|
self.incoming.push(UnboundedReceiverStream::new(incoming));
|
||||||
|
|
||||||
|
entry.insert((id, client.clone()));
|
||||||
|
Ok(Some(client))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn restart(
|
||||||
|
&mut self,
|
||||||
|
language_config: &LanguageConfiguration,
|
||||||
|
path: Option<&PathBuf>,
|
||||||
|
) -> Result<Arc<Client>> {
|
||||||
|
let config = language_config
|
||||||
|
.language_server
|
||||||
|
.as_ref()
|
||||||
|
.ok_or(Error::LspNotDefined)?;
|
||||||
|
let id = self
|
||||||
|
.inner
|
||||||
|
.get(&language_config.scope)
|
||||||
|
.ok_or(Error::LspNotDefined)?
|
||||||
|
.0;
|
||||||
|
let new_client = self.initialize_client(language_config, config, id, path)?;
|
||||||
|
let (_, client) = self
|
||||||
|
.inner
|
||||||
|
.get_mut(&language_config.scope)
|
||||||
|
.ok_or(Error::LspNotDefined)?;
|
||||||
|
*client = new_client;
|
||||||
|
|
||||||
|
Ok(client.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn initialize_client(
|
||||||
|
&mut self,
|
||||||
|
language_config: &LanguageConfiguration,
|
||||||
|
config: &helix_core::syntax::LanguageServerConfiguration,
|
||||||
|
id: usize,
|
||||||
|
path: Option<&PathBuf>,
|
||||||
|
) -> Result<Arc<Client>> {
|
||||||
|
let (client, incoming, initialize_notify) = Client::start(
|
||||||
|
&config.command,
|
||||||
|
&config.args,
|
||||||
|
language_config.config.clone(),
|
||||||
|
&language_config.roots,
|
||||||
|
id,
|
||||||
|
config.timeout,
|
||||||
|
path,
|
||||||
|
)?;
|
||||||
|
self.incoming.push(UnboundedReceiverStream::new(incoming));
|
||||||
|
let client = Arc::new(client);
|
||||||
|
|
||||||
|
// Initialize the client asynchronously
|
||||||
|
let _client = client.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
use futures_util::TryFutureExt;
|
||||||
|
let value = _client
|
||||||
|
.capabilities
|
||||||
|
.get_or_try_init(|| {
|
||||||
|
_client
|
||||||
|
.initialize()
|
||||||
|
.map_ok(|response| response.capabilities)
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
if let Err(e) = value {
|
||||||
|
log::error!("failed to initialize language server: {}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// next up, notify<initialized>
|
||||||
|
_client
|
||||||
|
.notify::<lsp::notification::Initialized>(lsp::InitializedParams {})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
initialize_notify.notify_one();
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(client)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter_clients(&self) -> impl Iterator<Item = &Arc<Client>> {
|
||||||
|
self.inner.values().map(|(_, client)| client)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ProgressStatus {
|
||||||
|
Created,
|
||||||
|
Started(lsp::WorkDoneProgress),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProgressStatus {
|
||||||
|
pub fn progress(&self) -> Option<&lsp::WorkDoneProgress> {
|
||||||
|
match &self {
|
||||||
|
ProgressStatus::Created => None,
|
||||||
|
ProgressStatus::Started(progress) => Some(progress),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug)]
|
||||||
|
/// Acts as a container for progress reported by language servers. Each server
|
||||||
|
/// has a unique id assigned at creation through [`Registry`]. This id is then used
|
||||||
|
/// to store the progress in this map.
|
||||||
|
pub struct LspProgressMap(HashMap<usize, HashMap<lsp::ProgressToken, ProgressStatus>>);
|
||||||
|
|
||||||
|
impl LspProgressMap {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a map of all tokens corresponding to the language server with `id`.
|
||||||
|
pub fn progress_map(&self, id: usize) -> Option<&HashMap<lsp::ProgressToken, ProgressStatus>> {
|
||||||
|
self.0.get(&id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_progressing(&self, id: usize) -> bool {
|
||||||
|
self.0.get(&id).map(|it| !it.is_empty()).unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns last progress status for a given server with `id` and `token`.
|
||||||
|
pub fn progress(&self, id: usize, token: &lsp::ProgressToken) -> Option<&ProgressStatus> {
|
||||||
|
self.0.get(&id).and_then(|values| values.get(token))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if progress `token` for server with `id` is created.
|
||||||
|
pub fn is_created(&mut self, id: usize, token: &lsp::ProgressToken) -> bool {
|
||||||
|
self.0
|
||||||
|
.get(&id)
|
||||||
|
.map(|values| values.get(token).is_some())
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create(&mut self, id: usize, token: lsp::ProgressToken) {
|
||||||
|
self.0
|
||||||
|
.entry(id)
|
||||||
|
.or_default()
|
||||||
|
.insert(token, ProgressStatus::Created);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ends the progress by removing the `token` from server with `id`, if removed returns the value.
|
||||||
|
pub fn end_progress(
|
||||||
|
&mut self,
|
||||||
|
id: usize,
|
||||||
|
token: &lsp::ProgressToken,
|
||||||
|
) -> Option<ProgressStatus> {
|
||||||
|
self.0.get_mut(&id).and_then(|vals| vals.remove(token))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates the progress of `token` for server with `id` to `status`, returns the value replaced or `None`.
|
||||||
|
pub fn update(
|
||||||
|
&mut self,
|
||||||
|
id: usize,
|
||||||
|
token: lsp::ProgressToken,
|
||||||
|
status: lsp::WorkDoneProgress,
|
||||||
|
) -> Option<ProgressStatus> {
|
||||||
|
self.0
|
||||||
|
.entry(id)
|
||||||
|
.or_default()
|
||||||
|
.insert(token, ProgressStatus::Started(status))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NewClientResult(Arc<Client>, UnboundedReceiver<(usize, Call)>);
|
||||||
|
|
||||||
|
/// start_client takes both a LanguageConfiguration and a LanguageServerConfiguration to ensure that
|
||||||
|
/// it is only called when it makes sense.
|
||||||
|
fn start_client(
|
||||||
|
id: usize,
|
||||||
|
config: &LanguageConfiguration,
|
||||||
|
ls_config: &LanguageServerConfiguration,
|
||||||
|
doc_path: Option<&std::path::PathBuf>,
|
||||||
|
) -> Result<NewClientResult> {
|
||||||
|
let (client, incoming, initialize_notify) = Client::start(
|
||||||
|
&ls_config.command,
|
||||||
|
&ls_config.args,
|
||||||
|
config.config.clone(),
|
||||||
|
&config.roots,
|
||||||
|
id,
|
||||||
|
ls_config.timeout,
|
||||||
|
doc_path,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let client = Arc::new(client);
|
||||||
|
|
||||||
|
// Initialize the client asynchronously
|
||||||
|
let _client = client.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
use futures_util::TryFutureExt;
|
||||||
|
let value = _client
|
||||||
|
.capabilities
|
||||||
|
.get_or_try_init(|| {
|
||||||
|
_client
|
||||||
|
.initialize()
|
||||||
|
.map_ok(|response| response.capabilities)
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
if let Err(e) = value {
|
||||||
|
log::error!("failed to initialize language server: {}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// next up, notify<initialized>
|
||||||
|
_client
|
||||||
|
.notify::<lsp::notification::Initialized>(lsp::InitializedParams {})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
initialize_notify.notify_one();
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(NewClientResult(client, incoming))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::{lsp, util::*, OffsetEncoding};
|
||||||
|
use helix_core::Rope;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn converts_lsp_pos_to_pos() {
|
||||||
|
macro_rules! test_case {
|
||||||
|
($doc:expr, ($x:expr, $y:expr) => $want:expr) => {
|
||||||
|
let doc = Rope::from($doc);
|
||||||
|
let pos = lsp::Position::new($x, $y);
|
||||||
|
assert_eq!($want, lsp_pos_to_pos(&doc, pos, OffsetEncoding::Utf16));
|
||||||
|
assert_eq!($want, lsp_pos_to_pos(&doc, pos, OffsetEncoding::Utf8))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
test_case!("", (0, 0) => Some(0));
|
||||||
|
test_case!("", (0, 1) => None);
|
||||||
|
test_case!("", (1, 0) => None);
|
||||||
|
test_case!("\n\n", (0, 0) => Some(0));
|
||||||
|
test_case!("\n\n", (1, 0) => Some(1));
|
||||||
|
test_case!("\n\n", (1, 1) => Some(2));
|
||||||
|
test_case!("\n\n", (2, 0) => Some(2));
|
||||||
|
test_case!("\n\n", (3, 0) => None);
|
||||||
|
test_case!("test\n\n\n\ncase", (4, 3) => Some(11));
|
||||||
|
test_case!("test\n\n\n\ncase", (4, 4) => Some(12));
|
||||||
|
test_case!("test\n\n\n\ncase", (4, 5) => None);
|
||||||
|
test_case!("", (u32::MAX, u32::MAX) => None);
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,73 @@
|
|||||||
|
; Keywords
|
||||||
|
|
||||||
|
[
|
||||||
|
"module"
|
||||||
|
"var"
|
||||||
|
"param"
|
||||||
|
"import"
|
||||||
|
"resource"
|
||||||
|
"existing"
|
||||||
|
"if"
|
||||||
|
"targetScope"
|
||||||
|
"output"
|
||||||
|
] @keyword
|
||||||
|
|
||||||
|
; Functions
|
||||||
|
|
||||||
|
(decorator) @function.builtin
|
||||||
|
|
||||||
|
(functionCall) @function
|
||||||
|
|
||||||
|
(functionCall
|
||||||
|
(functionArgument
|
||||||
|
(variableAccess) @variable))
|
||||||
|
|
||||||
|
; Literals/Types
|
||||||
|
|
||||||
|
[
|
||||||
|
"("
|
||||||
|
")"
|
||||||
|
"["
|
||||||
|
"]"
|
||||||
|
"{"
|
||||||
|
"}"
|
||||||
|
] @punctuation.bracket
|
||||||
|
|
||||||
|
(resourceDeclaration
|
||||||
|
(string
|
||||||
|
(stringLiteral) @string.special))
|
||||||
|
|
||||||
|
(moduleDeclaration
|
||||||
|
(string
|
||||||
|
(stringLiteral) @string.special))
|
||||||
|
|
||||||
|
[
|
||||||
|
(string)
|
||||||
|
(stringLiteral)
|
||||||
|
] @string
|
||||||
|
|
||||||
|
(nullLiteral) @keyword
|
||||||
|
(booleanLiteral) @constant.builtin.boolean
|
||||||
|
(integerLiteral) @constant.numeric.integer
|
||||||
|
(comment) @comment
|
||||||
|
|
||||||
|
(string
|
||||||
|
(variableAccess
|
||||||
|
(identifier) @variable))
|
||||||
|
|
||||||
|
(type) @type
|
||||||
|
|
||||||
|
; Variables
|
||||||
|
|
||||||
|
(localVariable) @variable
|
||||||
|
|
||||||
|
; Statements
|
||||||
|
|
||||||
|
(object
|
||||||
|
(objectProperty
|
||||||
|
(identifier) @identifier))
|
||||||
|
|
||||||
|
(propertyAccess
|
||||||
|
(identifier) @identifier)
|
||||||
|
|
||||||
|
(ifCondition) @keyword.control.conditional
|
@ -0,0 +1,13 @@
|
|||||||
|
[
|
||||||
|
(after_block)
|
||||||
|
(anonymous_function)
|
||||||
|
(catch_block)
|
||||||
|
(do_block)
|
||||||
|
(else_block)
|
||||||
|
(rescue_block)
|
||||||
|
(stab_clause)
|
||||||
|
] @indent
|
||||||
|
|
||||||
|
[
|
||||||
|
"end"
|
||||||
|
] @outdent
|
@ -1,2 +1,7 @@
|
|||||||
((comment_content) @injection.content
|
((line_comment (comment_content) @injection.content)
|
||||||
(#set! injection.language "edoc"))
|
(#set! injection.language "edoc")
|
||||||
|
(#set! injection.include-children)
|
||||||
|
(#set! injection.combined))
|
||||||
|
|
||||||
|
((comment (comment_content) @injection.content)
|
||||||
|
(#set! injection.language "comment"))
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
; Specs and Callbacks
|
||||||
|
(attribute
|
||||||
|
(stab_clause
|
||||||
|
pattern: (arguments (variable) @local.definition)
|
||||||
|
; If a spec uses a variable as the return type (and later a `when` clause to type it):
|
||||||
|
body: (variable)? @local.definition)) @local.scope
|
||||||
|
|
||||||
|
; parametric `-type`s
|
||||||
|
((attribute
|
||||||
|
name: (atom) @_type
|
||||||
|
(arguments
|
||||||
|
(binary_operator
|
||||||
|
left: (call (arguments (variable) @local.definition))
|
||||||
|
operator: "::") @local.scope))
|
||||||
|
(#match? @_type "(type|opaque)"))
|
||||||
|
|
||||||
|
; macros
|
||||||
|
((attribute
|
||||||
|
name: (atom) @_define
|
||||||
|
(arguments
|
||||||
|
(call (arguments (variable) @local.definition)))) @local.scope
|
||||||
|
(#eq? @_define "define"))
|
||||||
|
|
||||||
|
; `fun`s
|
||||||
|
(anonymous_function (stab_clause pattern: (arguments (variable) @local.definition))) @local.scope
|
||||||
|
|
||||||
|
; Ordinary functions
|
||||||
|
(function_clause pattern: (arguments (variable) @local.definition)) @local.scope
|
||||||
|
|
||||||
|
(variable) @local.reference
|
@ -1,2 +1,2 @@
|
|||||||
((comment) @injection.content
|
([(line_comment) (block_comment)] @injection.content
|
||||||
(#set! injection.language "comment"))
|
(#set! injection.language "comment"))
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
(method_declaration
|
||||||
|
body: (_) @function.inside) @function.around
|
||||||
|
|
||||||
|
(interface_declaration
|
||||||
|
body: (_) @class.inside) @class.around
|
||||||
|
|
||||||
|
(class_declaration
|
||||||
|
body: (_) @class.inside) @class.around
|
||||||
|
|
||||||
|
(record_declaration
|
||||||
|
body: (_) @class.inside) @class.around
|
||||||
|
|
||||||
|
(enum_declaration
|
||||||
|
body: (_) @class.inside) @class.around
|
||||||
|
|
||||||
|
(formal_parameters
|
||||||
|
((_) @parameter.inside . ","? @parameter.around) @parameter.around)
|
||||||
|
|
||||||
|
(type_parameters
|
||||||
|
((_) @parameter.inside . ","? @parameter.around) @parameter.around)
|
||||||
|
|
||||||
|
(type_arguments
|
||||||
|
((_) @parameter.inside . ","? @parameter.around) @parameter.around)
|
||||||
|
|
||||||
|
(argument_list
|
||||||
|
((_) @parameter.inside . ","? @parameter.around) @parameter.around)
|
||||||
|
|
||||||
|
[
|
||||||
|
(line_comment)
|
||||||
|
(block_comment)
|
||||||
|
] @comment.inside
|
||||||
|
|
||||||
|
(line_comment)+ @comment.around
|
||||||
|
|
||||||
|
(block_comment) @comment.around
|
@ -1,62 +1,62 @@
|
|||||||
(string_literal) @string
|
(comment) @comment
|
||||||
|
|
||||||
(boolean_literal) @constant.builtin.boolean
|
; these are listed first, because they override keyword queries
|
||||||
(integer_literal) @constant.numeric.integer
|
(function_expression (identifier) @function)
|
||||||
|
|
||||||
(comment) @comment.line
|
|
||||||
(function_id) @function
|
|
||||||
(keyword_arg_key) @variable.other.member
|
|
||||||
(id_expression) @variable
|
|
||||||
|
|
||||||
[
|
[
|
||||||
"if"
|
(assignment_operator)
|
||||||
"elif"
|
(additive_operator)
|
||||||
"else"
|
(multiplicative_operator)
|
||||||
"endif"
|
(equality_operator)
|
||||||
] @keyword.control.conditional
|
">="
|
||||||
|
"<="
|
||||||
|
"<"
|
||||||
|
">"
|
||||||
|
"+"
|
||||||
|
"-"
|
||||||
|
] @operator
|
||||||
|
|
||||||
[
|
[
|
||||||
"foreach"
|
(and)
|
||||||
"endforeach"
|
(or)
|
||||||
] @keyword.control.repeat
|
(not)
|
||||||
|
(in)
|
||||||
|
] @keyword.operator
|
||||||
|
|
||||||
[
|
[
|
||||||
"break"
|
"(" ")" "[" "]" "{" "}"
|
||||||
"continue"
|
] @punctuation.bracket
|
||||||
] @keyword.control
|
|
||||||
|
|
||||||
[
|
[
|
||||||
"not"
|
(if)
|
||||||
"in"
|
(elif)
|
||||||
"and"
|
(else)
|
||||||
"or"
|
(endif)
|
||||||
] @keyword.operator
|
] @keyword.control.conditional
|
||||||
|
|
||||||
[
|
[
|
||||||
"!"
|
(foreach)
|
||||||
"+"
|
(endforeach)
|
||||||
"-"
|
(break)
|
||||||
"*"
|
(continue)
|
||||||
"/"
|
] @keyword.control.repeat
|
||||||
"%"
|
|
||||||
"=="
|
(boolean_literal) @constant.builtin.boolean
|
||||||
"!="
|
(int_literal) @constant.numeric.integer
|
||||||
">"
|
|
||||||
"<"
|
(keyword_argument keyword: (identifier) @variable.parameter)
|
||||||
">="
|
(escape_sequence) @constant.character.escape
|
||||||
"<="
|
(bad_escape) @warning
|
||||||
] @operator
|
|
||||||
|
|
||||||
[
|
[
|
||||||
":"
|
"."
|
||||||
","
|
","
|
||||||
|
":"
|
||||||
] @punctuation.delimiter
|
] @punctuation.delimiter
|
||||||
|
|
||||||
[
|
[
|
||||||
"("
|
(string_literal)
|
||||||
")"
|
(fstring_literal)
|
||||||
"["
|
] @string
|
||||||
"]"
|
|
||||||
"{"
|
(identifier) @variable
|
||||||
"}"
|
|
||||||
] @punctuation.bracket
|
|
||||||
|
@ -0,0 +1,90 @@
|
|||||||
|
(comment) @comment
|
||||||
|
|
||||||
|
(ui_import
|
||||||
|
source: _ @namespace
|
||||||
|
version: _? @constant
|
||||||
|
alias: _? @namespace)
|
||||||
|
|
||||||
|
(ui_pragma
|
||||||
|
name: (identifier) @attribute
|
||||||
|
value: (identifier)? @constant)
|
||||||
|
|
||||||
|
(ui_annotation
|
||||||
|
"@" @punctuation
|
||||||
|
type_name: _ @type)
|
||||||
|
|
||||||
|
;;; Declarations
|
||||||
|
|
||||||
|
(enum_declaration
|
||||||
|
name: (identifier) @type)
|
||||||
|
|
||||||
|
(enum_assignment
|
||||||
|
name: (identifier) @constant
|
||||||
|
value: _ @constant)
|
||||||
|
|
||||||
|
(enum_body
|
||||||
|
name: (identifier) @constant)
|
||||||
|
|
||||||
|
(ui_inline_component
|
||||||
|
name: (identifier) @type)
|
||||||
|
|
||||||
|
(ui_object_definition
|
||||||
|
type_name: _ @type)
|
||||||
|
|
||||||
|
(ui_object_definition_binding
|
||||||
|
type_name: _ @type
|
||||||
|
name: _ @variable.other.member)
|
||||||
|
|
||||||
|
(ui_property
|
||||||
|
type: _ @type
|
||||||
|
name: (identifier) @variable.other.member)
|
||||||
|
|
||||||
|
(ui_signal
|
||||||
|
name: (identifier) @function)
|
||||||
|
|
||||||
|
(ui_signal_parameter
|
||||||
|
name: (identifier) @variable.parameter
|
||||||
|
type: _ @type)
|
||||||
|
|
||||||
|
(ui_signal_parameter
|
||||||
|
type: _ @type
|
||||||
|
name: (identifier) @variable.parameter);;; Properties and bindings
|
||||||
|
|
||||||
|
;;; Bindings
|
||||||
|
|
||||||
|
(ui_binding
|
||||||
|
name: _ @variable.other.member)
|
||||||
|
|
||||||
|
;;; Other
|
||||||
|
|
||||||
|
[
|
||||||
|
"("
|
||||||
|
")"
|
||||||
|
"{"
|
||||||
|
"}"
|
||||||
|
] @punctuation.bracket
|
||||||
|
|
||||||
|
(ui_list_property_type [
|
||||||
|
"<"
|
||||||
|
">"
|
||||||
|
] @punctuation.bracket)
|
||||||
|
|
||||||
|
[
|
||||||
|
","
|
||||||
|
"."
|
||||||
|
":"
|
||||||
|
] @punctuation.delimiter
|
||||||
|
|
||||||
|
[
|
||||||
|
"as"
|
||||||
|
"component"
|
||||||
|
"default"
|
||||||
|
"enum"
|
||||||
|
"import"
|
||||||
|
"on"
|
||||||
|
"pragma"
|
||||||
|
"property"
|
||||||
|
"readonly"
|
||||||
|
"required"
|
||||||
|
"signal"
|
||||||
|
] @keyword
|
@ -0,0 +1,6 @@
|
|||||||
|
[
|
||||||
|
(enum_body)
|
||||||
|
(ui_object_initializer)
|
||||||
|
] @indent
|
||||||
|
|
||||||
|
"}" @outdent
|
@ -0,0 +1,16 @@
|
|||||||
|
((comment) @injection.content
|
||||||
|
(#set! injection.language "comment"))
|
||||||
|
|
||||||
|
([
|
||||||
|
(empty_statement)
|
||||||
|
(expression_statement)
|
||||||
|
(function_declaration)
|
||||||
|
(generator_function_declaration)
|
||||||
|
(statement_block)
|
||||||
|
(switch_statement)
|
||||||
|
(try_statement)
|
||||||
|
(variable_declaration)
|
||||||
|
(with_statement)
|
||||||
|
] @injection.content
|
||||||
|
(#set! injection.include-children)
|
||||||
|
(#set! injection.language "javascript"))
|
@ -0,0 +1,138 @@
|
|||||||
|
# Author : Rohit K Viswanath <kvrohit@gmail.com>
|
||||||
|
# Theme: Mellow
|
||||||
|
|
||||||
|
"attribute" = { fg = "blue", modifiers = ["italic"] }
|
||||||
|
|
||||||
|
"keyword" = "blue"
|
||||||
|
"keyword.control.conditional" = { fg = "blue", modifiers = ["italic"] }
|
||||||
|
"keyword.directive" = "magenta" # -- preprocessor comments (#if in C)
|
||||||
|
|
||||||
|
"namespace" = { fg = "cyan", modifiers = ["italic"] }
|
||||||
|
|
||||||
|
"punctuation" = "gray06"
|
||||||
|
"punctuation.delimiter" = "gray06"
|
||||||
|
|
||||||
|
"operator" = "yellow"
|
||||||
|
"special" = "yellow"
|
||||||
|
|
||||||
|
"variable" = "fg"
|
||||||
|
"variable.builtin" = "bright_blue"
|
||||||
|
"variable.parameter" = "cyan"
|
||||||
|
"variable.other.member" = "white"
|
||||||
|
|
||||||
|
"type" = "bright_blue"
|
||||||
|
"type.builtin" = "magenta"
|
||||||
|
"type.enum.variant" = "magenta"
|
||||||
|
|
||||||
|
"constructor" = "yellow"
|
||||||
|
|
||||||
|
"function" = "white"
|
||||||
|
"function.macro" = "bright_cyan"
|
||||||
|
"function.builtin" = "bright_blue"
|
||||||
|
|
||||||
|
"tag" = "cyan"
|
||||||
|
"comment" = { fg = "gray05", modifiers = ["italic"] }
|
||||||
|
|
||||||
|
"string" = "green"
|
||||||
|
"string.regexp" = "green"
|
||||||
|
"string.special" = "yellow"
|
||||||
|
|
||||||
|
"constant" = "cyan"
|
||||||
|
"constant.builtin" = "yellow"
|
||||||
|
"constant.numeric" = "magenta"
|
||||||
|
"constant.character.escape" = "cyan"
|
||||||
|
|
||||||
|
# used for lifetimes
|
||||||
|
"label" = "yellow"
|
||||||
|
|
||||||
|
"markup.heading.marker" = { fg = "gray06" }
|
||||||
|
"markup.heading" = { fg = "bright_blue", modifiers = ["bold"] }
|
||||||
|
"markup.list" = "gray06"
|
||||||
|
"markup.bold" = { modifiers = ["bold"] }
|
||||||
|
"markup.italic" = { modifiers = ["italic"] }
|
||||||
|
"markup.link.url" = { fg = "green", modifiers = ["underlined"] }
|
||||||
|
"markup.link.text" = { fg = "blue", modifiers = ["italic"] }
|
||||||
|
"markup.raw" = "yellow"
|
||||||
|
|
||||||
|
"diff.plus" = "bright_green"
|
||||||
|
"diff.minus" = "bright_red"
|
||||||
|
"diff.delta" = "bright_blue"
|
||||||
|
|
||||||
|
"ui.background" = { bg = "bg" }
|
||||||
|
"ui.background.separator" = { fg = "fg" }
|
||||||
|
|
||||||
|
"ui.linenr" = { fg = "gray04" }
|
||||||
|
"ui.linenr.selected" = { fg = "fg" }
|
||||||
|
|
||||||
|
"ui.statusline" = { fg = "fg", bg = "gray01" }
|
||||||
|
"ui.statusline.inactive" = { fg = "fg", bg = "gray01", modifiers = ["dim"] }
|
||||||
|
"ui.statusline.normal" = { fg = "bg", bg = "cyan", modifiers = ["bold"] }
|
||||||
|
"ui.statusline.insert" = { fg = "bg", bg = "blue", modifiers = ["bold"] }
|
||||||
|
"ui.statusline.select" = { fg = "bg", bg = "magenta", modifiers = ["bold"] }
|
||||||
|
|
||||||
|
"ui.popup" = { bg = "gray01" }
|
||||||
|
"ui.window" = { fg = "gray02" }
|
||||||
|
"ui.help" = { bg = "gray01", fg = "white" }
|
||||||
|
|
||||||
|
"ui.text" = { fg = "fg" }
|
||||||
|
"ui.text.focus" = { fg = "fg" }
|
||||||
|
|
||||||
|
"ui.virtual" = { fg = "gray02" }
|
||||||
|
"ui.virtual.indent-guide" = { fg = "gray02" }
|
||||||
|
|
||||||
|
"ui.selection" = { bg = "gray03" }
|
||||||
|
"ui.selection.primary" = { bg = "gray03" }
|
||||||
|
|
||||||
|
"ui.cursor" = { bg = "gray04" }
|
||||||
|
"ui.cursor.match" = { fg = "yellow", modifiers = ["bold", "underlined"] }
|
||||||
|
"ui.cursorline.primary" = { bg = "gray01" }
|
||||||
|
|
||||||
|
"ui.highlight" = { bg = "gray02" }
|
||||||
|
|
||||||
|
"ui.menu" = { fg = "white", bg = "gray01" }
|
||||||
|
"ui.menu.selected" = { fg = "bright_white", bg = "gray03" }
|
||||||
|
"ui.menu.scroll" = { fg = "gray04", bg = "gray01" }
|
||||||
|
|
||||||
|
diagnostic = { modifiers = ["underlined"] }
|
||||||
|
|
||||||
|
warning = "bright_yellow"
|
||||||
|
error = "bright_red"
|
||||||
|
info = "bright_blue"
|
||||||
|
hint = "bright_cyan"
|
||||||
|
|
||||||
|
[palette]
|
||||||
|
bg = "#161617"
|
||||||
|
fg = "#c9c7cd"
|
||||||
|
bg_dark = "#131314"
|
||||||
|
|
||||||
|
black = "#27272a"
|
||||||
|
bright_black = "#353539"
|
||||||
|
|
||||||
|
red = "#f5a191"
|
||||||
|
bright_red = "#ffae9f"
|
||||||
|
|
||||||
|
green = "#90b99f"
|
||||||
|
bright_green = "#9dc6ac"
|
||||||
|
|
||||||
|
yellow = "#e6b99d"
|
||||||
|
bright_yellow = "#f0c5a9"
|
||||||
|
|
||||||
|
blue = "#aca1cf"
|
||||||
|
bright_blue = "#b9aeda"
|
||||||
|
|
||||||
|
magenta = "#e29eca"
|
||||||
|
bright_magenta = "#ecaad6"
|
||||||
|
|
||||||
|
cyan = "#ea83a5"
|
||||||
|
bright_cyan = "#f591b2"
|
||||||
|
|
||||||
|
white = "#c1c0d4"
|
||||||
|
bright_white = "#cac9dd"
|
||||||
|
|
||||||
|
gray01 = "#1b1b1d"
|
||||||
|
gray02 = "#2a2a2d"
|
||||||
|
gray03 = "#3e3e43"
|
||||||
|
gray04 = "#57575f"
|
||||||
|
gray05 = "#757581"
|
||||||
|
gray06 = "#9998a8"
|
||||||
|
gray07 = "#c1c0d4"
|
@ -0,0 +1,182 @@
|
|||||||
|
# Author: github.com/jhscheer
|
||||||
|
#
|
||||||
|
# This theme is an adaptation of
|
||||||
|
# github.com/EdenEast/nightfox.nvim
|
||||||
|
|
||||||
|
|
||||||
|
# INTERFACE
|
||||||
|
# These scopes are used for theming the editor interface.
|
||||||
|
|
||||||
|
"ui.background" = { bg = "bg1" } # Default background color.
|
||||||
|
"ui.window" = { fg = "bg0" } # Window border between splits.
|
||||||
|
"ui.gutter" = { fg = "fg3" } # Left gutter for diagnostics and breakpoints.
|
||||||
|
|
||||||
|
"ui.text" = { fg = "fg1" } # Default text color.
|
||||||
|
"ui.text.focus" = { bg = "sel1", fg = "fg1" } # Selection highlight in buffer-picker or file-picker.
|
||||||
|
"ui.text.info" = { fg = "fg2", bg = "sel0" } # Info popup contents (space mode menu).
|
||||||
|
|
||||||
|
"ui.cursor" = { bg = "fg3", fg = "bg1" } # Fallback cursor colour, non-primary cursors when there are multiple (shift-c).
|
||||||
|
"ui.cursor.primary" = { bg = "fg1", fg = "bg1" } # The primary cursor when there are multiple (shift-c).
|
||||||
|
"ui.cursor.match" = { fg = "yellow", modifiers = ["bold"] } # The matching parentheses of that under the cursor.
|
||||||
|
|
||||||
|
"ui.selection" = { bg = "bg3" } # All currently selected text.
|
||||||
|
"ui.selection.primary" = { bg = "bg4" } # The primary selection when there are multiple.
|
||||||
|
"ui.cursorline.primary" = { bg = "bg3" } # The line of the primary cursor (if cursorline is enabled)
|
||||||
|
# "ui.cursorline.secondary" = { } # The lines of any other cursors (if cursorline is enabled)
|
||||||
|
# "ui.cursorcolumn.primary" = { } # The column of the primary cursor (if cursorcolumn is enabled)
|
||||||
|
# "ui.cursorcolumn.secondary" = { } # The columns of any other cursors (if cursorcolumn is enabled)
|
||||||
|
|
||||||
|
"ui.linenr" = { fg = "fg3" } # Line numbers.
|
||||||
|
"ui.linenr.selected" = { fg = "yellow", modifiers = ["bold"] } # Current line number.
|
||||||
|
|
||||||
|
# "ui.virtual" = { } # Namespace for additions to the editing area.
|
||||||
|
"ui.virtual.ruler" = { bg = "bg3" } # Vertical rulers (colored columns in editing area).
|
||||||
|
"ui.virtual.whitespace" = { fg = "bg3" } # Whitespace markers in editing area.
|
||||||
|
"ui.virtual.indent-guide" = { fg = "black" } # Vertical indent width guides
|
||||||
|
|
||||||
|
"ui.statusline" = { fg = "fg2", bg = "bg0" } # Status line.
|
||||||
|
"ui.statusline.inactive" = { fg = "fg3", bg = "bg0" } # Status line in unfocused windows.
|
||||||
|
"ui.statusline.normal" = { bg = "blue", fg = "bg0", modifiers = ["bold"] } # Statusline mode during normal mode (only if editor.color-modes is enabled)
|
||||||
|
"ui.statusline.insert" = { bg = "green", fg = "bg0", modifiers = ["bold"] } # Statusline mode during insert mode (only if editor.color-modes is enabled)
|
||||||
|
"ui.statusline.select" = { bg = "magenta", fg = "bg0", modifiers = ["bold"] } # Statusline mode during select mode (only if editor.color-modes is enabled)
|
||||||
|
|
||||||
|
"ui.help" = { bg = "sel0", fg = "fg1" } # Description box for commands.
|
||||||
|
|
||||||
|
"ui.menu" = { bg = "sel0", fg = "fg1" } # Code and command completion menus.
|
||||||
|
"ui.menu.selected" = { bg = "fg3" } # Selected autocomplete item.
|
||||||
|
"ui.menu.scroll" = { fg = "fg3" } # fg sets thumb color, bg sets track color of scrollbar.
|
||||||
|
|
||||||
|
"ui.popup" = { bg = "bg0", fg = "fg1" } # Documentation popups (space-k).
|
||||||
|
"ui.popup.info" = { bg = "sel0", fg = "fg1" } # Info popups box (space mode menu).
|
||||||
|
|
||||||
|
"markup.raw" = { fg = "magenta" } # Code block in Markdown.
|
||||||
|
"markup.raw.inline" = { fg = "orange" } # `Inline code block` in Markdown.
|
||||||
|
"markup.heading" = { fg = "yellow", modifiers = ["bold"] }
|
||||||
|
"markup.list" = { fg = "magenta", modifiers = ["bold"] }
|
||||||
|
"markup.bold" = { fg = "orange", modifiers = ["bold"] }
|
||||||
|
"markup.italic" = { fg = "pink" }
|
||||||
|
"markup.link" = { fg = "yellow-bright", modifiers = ["bold"] }
|
||||||
|
"markup.quote" = { fg = "blue" }
|
||||||
|
|
||||||
|
|
||||||
|
# DIAGNOSTICS
|
||||||
|
"warning" = { fg ="yellow", bg = "bg1" } # Diagnostics warning (gutter)
|
||||||
|
"error" = { fg = "red", bg = "bg1" } # Diagnostics error (gutter)
|
||||||
|
"info" = { fg = "blue", bg = "bg1" } # Diagnostics info (gutter)
|
||||||
|
"hint" = { fg = "green", bg = "bg1" } # Diagnostics hint (gutter)
|
||||||
|
"diagnostic" = { modifiers = ["underlined"] } # Diagnostics fallback style (editing area)
|
||||||
|
"diagnostic.error" = { fg = "red" } # Diagnostics error (editing area)
|
||||||
|
"diagnostic.warning" = { fg = "yellow" } # Diagnostics warning (editing area)
|
||||||
|
"diagnostic.info" = { fg = "blue" } # Diagnostics info (editing area)
|
||||||
|
"diagnostic.hint" = { fg = "green" } # Diagnostics hint (editing area)
|
||||||
|
|
||||||
|
|
||||||
|
# SYNTAX HIGHLIGHTING
|
||||||
|
# These keys match tree-sitter scopes.
|
||||||
|
|
||||||
|
"special" = { fg = "fg2" } # Special symbols e.g `?` in Rust, `...` in Hare.
|
||||||
|
"attribute" = { fg = "yellow" } # Class attributes, html tag attributes.
|
||||||
|
|
||||||
|
"type" = { fg = "yellow" } # Variable type, like integer or string, including program defined classes, structs etc..
|
||||||
|
"type.builtin" = { fg = "cyan-bright" } # Primitive types of the language (string, int, float).
|
||||||
|
"type.enum.variant" = { fg = "orange-bright" }
|
||||||
|
|
||||||
|
"constructor" = { fg = "magenta" } # Constructor method for a class or struct.
|
||||||
|
|
||||||
|
"constant" = { fg = "orange-bright" } # Constant value
|
||||||
|
"constant.builtin" = { fg = "orange-bright" } # Special constants like `true`, `false`, `none`, etc.
|
||||||
|
"constant.builtin.boolean" = { fg = "orange" } # True or False.
|
||||||
|
"constant.character" = { fg = "green" } # Constant of character type.
|
||||||
|
"constant.character.escape" = { fg = "yellow-bright", modifiers = ["bold"] } # escape codes like \n.
|
||||||
|
"constant.numeric" = { fg = "orange" } # constant integer or float value.
|
||||||
|
|
||||||
|
"string" = { fg = "green" } # String literal.
|
||||||
|
"string.regexp" = { fg = "yellow-bright" } # Regular expression literal.
|
||||||
|
"string.special" = { fg = "yellow-bright", modifiers = ["bold"] } # Strings containing a path, URL, etc.
|
||||||
|
"string.special.url" = { fg = "cyan", modifiers = ["bold"] } # String containing a web URL.
|
||||||
|
|
||||||
|
"comment" = { fg = "comment" } # This is a comment.
|
||||||
|
"comment.block.documentation" = { fg = "comment", modifiers = ["bold"] } # Doc comments, e.g '///' in rust.
|
||||||
|
|
||||||
|
"variable" = { fg = "white" } # Variable names.
|
||||||
|
"variable.builtin" = { fg = "red" } # Language reserved variables: `this`, `self`, `super`, etc.
|
||||||
|
"variable.parameter" = { fg = "cyan-bright" } # Function parameters.
|
||||||
|
"variable.other.member" = { fg = "fg2" } # Fields of composite data types (e.g. structs, unions).
|
||||||
|
|
||||||
|
"label" = { fg = "magenta-bright" } # lifetimes - Loop labels, among other things.
|
||||||
|
|
||||||
|
"punctuation" = { fg = "fg2" } # Any punctuation symbol.
|
||||||
|
# "punctuation.delimiter" = { fg = "fg2" } # Commas, colons or other delimiter depending on the language.
|
||||||
|
# "punctuation.bracket" = { fg = "fg2" } # Parentheses, angle brackets, etc.
|
||||||
|
# "punctuation.special" = { fg = "fg2" } # String interpolation brackets
|
||||||
|
|
||||||
|
"keyword" = { fg = "magenta" } # Language reserved keywords.
|
||||||
|
"keyword.control" = { fg = "pink" } # Control keywords.
|
||||||
|
"keyword.control.conditional" = { fg = "magenta-bright" } # `if`, `else`, `elif`.
|
||||||
|
"keyword.control.repeat" = { fg = "magenta-bright" } # `for`, `while`, `loop`.
|
||||||
|
"keyword.control.import" = { fg = "pink-bright" } # `import`, `export` `use`.
|
||||||
|
"keyword.control.return" = { fg = "magenta" } # `return` in most languages.
|
||||||
|
"keyword.control.exception" = { fg = "magenta" } # `try`, `catch`, `raise`/`throw` and related.
|
||||||
|
"keyword.operator" = { fg = "fg2", modifiers = ["bold"] } # 'or', 'and', 'in'.
|
||||||
|
"keyword.directive" = { fg = "pink-bright" } # Preprocessor directives (#if in C...).
|
||||||
|
"keyword.function" = { fg = "red" } # The keyword to define a funtion: 'def', 'fun', 'fn'.
|
||||||
|
"keyword.storage" = { fg = "magenta" } # Keywords describing how things are stored
|
||||||
|
"keyword.storage.type" = { fg = "magenta" } # The type of something, class, function, var, let, etc.
|
||||||
|
"keyword.storage.modifier" = { fg = "yellow" } # Storage modifiers like static, mut, const, ref, etc.
|
||||||
|
|
||||||
|
"operator" = { fg = "fg2" } # Logical, mathematical, and other operators.
|
||||||
|
|
||||||
|
"function" = { fg = "blue-bright" }
|
||||||
|
"function.builtin" = { fg = "red" }
|
||||||
|
"function.macro" = { fg = "red" }
|
||||||
|
# "function.special" = { fg = "blue-bright" } # Preprocessor function in C.
|
||||||
|
# "function.method" = { fg = "blue-bright" } # Class / Struct methods.
|
||||||
|
|
||||||
|
"tag" = { fg = "blue-bright" } # As in <body> for html, css tags.
|
||||||
|
|
||||||
|
"namespace" = { fg = "cyan-bright" } # Namespace or module identifier.
|
||||||
|
|
||||||
|
|
||||||
|
# Diff ==============================
|
||||||
|
# Version control changes.
|
||||||
|
|
||||||
|
"diff.plus" = "green-dim" # Additions.
|
||||||
|
"diff.minus" = "red-dim" # Deletions.
|
||||||
|
"diff.delta" = "blue-dim" # Modifications.
|
||||||
|
"diff.delta.moved" = "cyan-dim" # Renamed or moved files.
|
||||||
|
|
||||||
|
# color palette
|
||||||
|
[palette]
|
||||||
|
black = "#393b44"
|
||||||
|
red = "#c94f6d"
|
||||||
|
red-dim = "#2f2837"
|
||||||
|
green = "#81b29a"
|
||||||
|
green-dim = "#26343c"
|
||||||
|
yellow = "#dbc074"
|
||||||
|
yellow-bright = "#e0c989"
|
||||||
|
blue = "#719cd6"
|
||||||
|
blue-bright = "#86abdc"
|
||||||
|
blue-dim = "#2f2837"
|
||||||
|
magenta = "#9d79d6"
|
||||||
|
magenta-bright = "#baa1e2"
|
||||||
|
cyan = "#63cdcf"
|
||||||
|
cyan-bright = "#7ad4d6"
|
||||||
|
cyan-dim = "#253f4a"
|
||||||
|
white = "#dfdfe0"
|
||||||
|
orange = "#f4a261"
|
||||||
|
orange-bright = "#f6b079"
|
||||||
|
pink = "#d67ad2"
|
||||||
|
pink-bright = "#dc8ed9"
|
||||||
|
comment = "#738091"
|
||||||
|
# spec
|
||||||
|
bg0 = "#131a24" # Dark bg (status line and float)
|
||||||
|
bg1 = "#192330" # Default bg
|
||||||
|
bg2 = "#212e3f" # Lighter bg (colorcolm folds)
|
||||||
|
bg3 = "#29394f" # Lighter bg (cursor line)
|
||||||
|
bg4 = "#39506d" # Conceal, border fg
|
||||||
|
fg0 = "#d6d6d7" # Lighter fg
|
||||||
|
fg1 = "#cdcecf" # Default fg
|
||||||
|
fg2 = "#aeafb0" # Darker fg (status line)
|
||||||
|
fg3 = "#71839b" # Darker fg (line numbers, fold colums)
|
||||||
|
sel0 = "#2b3b51" # Popup bg, visual selection bg
|
||||||
|
sel1 = "#3c5372" # Popup sel bg, search bg
|
@ -0,0 +1,60 @@
|
|||||||
|
# A unofficial port of VIM's zenburn theme: https://github.com/jnurmine/Zenburn/
|
||||||
|
|
||||||
|
"ui.background" = { bg = "bg" }
|
||||||
|
"ui.menu" = { fg = "#9f9f9f", bg = "uibg" }
|
||||||
|
"ui.menu.selected" = { fg = "#d0d0a0", bg = "#242424", modifiers = ["bold"] }
|
||||||
|
"ui.linenr" = { fg = "#9fafaf", bg = "#262626"}
|
||||||
|
"ui.linenr.selected" = { modifiers = ["bold"]}
|
||||||
|
"ui.popup" = { bg = "uibg" }
|
||||||
|
"ui.selection" = { bg = "#2f2f2f" }
|
||||||
|
"comment" = { fg = "#7f9f7f" }
|
||||||
|
"comment.block.documentation" = { fg = "black", modifiers = ["bold"] }
|
||||||
|
"ui.statusline" = { bg = "statusbg", fg = "#ccdc90" }
|
||||||
|
"ui.statusline.inactive" = { fg = '#2e3330', bg = '#88b090' }
|
||||||
|
"ui.cursor" = { fg = "#000d18", bg = "#8faf9f", modifiers = ["bold"] }
|
||||||
|
"ui.text" = { fg = "normal"}
|
||||||
|
"operator" = { fg = "#f0efd0" , modifiers = []}
|
||||||
|
"variable" = "normal"
|
||||||
|
"variable.builtin" = {fg = "constant", modifiers = ["bold"]}
|
||||||
|
"constant.numeric" = "numeric"
|
||||||
|
"constant" = { fg = "constant", modifiers = ["bold"] }
|
||||||
|
"type" = { fg = "#dfdfbf", modifiers = ["bold"] }
|
||||||
|
"ui.cursor.match" = { fg = "#343434", bg = "#284f28", modifiers = ["bold"] }
|
||||||
|
"string" = "#cc9393"
|
||||||
|
"variable.other.member" = "#efef8f"
|
||||||
|
"constant.character.escape" = { fg = "#dca3a3", modifiers = ["bold"]}
|
||||||
|
"function" = "#efef8f"
|
||||||
|
"function.macro" = { fg = "#ffcfaf", modifiers = ["bold"] }
|
||||||
|
"special" = "#cfbfaf"
|
||||||
|
"keyword" = { fg = "#f0dfaf", modifiers = ["bold"]}
|
||||||
|
"keyword.storage-class" = { fg = "#c3bf9f", modifiers = ["bold"]}
|
||||||
|
"label" = { fg = "#dfcfaf", modifiers = ["underlined"] }
|
||||||
|
"ui.help" = { fg = "white", bg = "black" }
|
||||||
|
"ui.virtual.ruler" = { bg = "#484848" }
|
||||||
|
"ui.virtual.whitespace" = { fg = "#5b605e", modifiers = ["bold"]}
|
||||||
|
|
||||||
|
"punctuation.delimiter" = "#8f8f8f"
|
||||||
|
|
||||||
|
"ui.virtual.indent-guide" = "#4f4f4f"
|
||||||
|
|
||||||
|
"diff.plus" = {fg = "#709080", bg = "#313c36", modifiers = ["bold"] }
|
||||||
|
"diff.delta" = "#333333"
|
||||||
|
"diff.minus" = {fg = "#333333", bg = "#464646"}
|
||||||
|
|
||||||
|
"diagnostic" = {bg = "statusbg"}
|
||||||
|
"diagnostic.error" = { fg = "errorfg", bg = "errorbg"}
|
||||||
|
"ui.gutter" = { bg = "statusbg" }
|
||||||
|
"hint" = {fg = "numeric", bg = "statusbg"}
|
||||||
|
"warning" = "numeric"
|
||||||
|
"error" = "errorfg"
|
||||||
|
|
||||||
|
[palette]
|
||||||
|
bg = "#3f3f3f"
|
||||||
|
uibg = "#2c2e2e"
|
||||||
|
constant = "#dca3a3"
|
||||||
|
normal = "#dcdccc"
|
||||||
|
todo = "#dfdfdf"
|
||||||
|
errorfg = "#e37170"
|
||||||
|
errorbg = "#3d3535"
|
||||||
|
statusbg = "#313633"
|
||||||
|
numeric = "#8cd0d3"
|
Loading…
Reference in New Issue