Add styles support
This commit is contained in:
parent
0fddb56b03
commit
f99a51e73a
6 changed files with 188 additions and 19 deletions
|
@ -14,6 +14,7 @@ use crate::parser::source::Token;
|
||||||
use crate::parser::state::RuleState;
|
use crate::parser::state::RuleState;
|
||||||
use crate::parser::state::Scope;
|
use crate::parser::state::Scope;
|
||||||
use ariadne::Fmt;
|
use ariadne::Fmt;
|
||||||
|
use lsp::styles::Styles;
|
||||||
use mlua::Function;
|
use mlua::Function;
|
||||||
use regex::Captures;
|
use regex::Captures;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
@ -188,6 +189,8 @@ impl RegexRule for StyleRule {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(style_state) = style_state.borrow_mut().downcast_mut::<StyleState>() {
|
if let Some(style_state) = style_state.borrow_mut().downcast_mut::<StyleState>() {
|
||||||
|
let start = style_state.toggled[index].clone();
|
||||||
|
|
||||||
style_state.toggled[index] = style_state.toggled[index]
|
style_state.toggled[index] = style_state.toggled[index]
|
||||||
.clone()
|
.clone()
|
||||||
.map_or(Some(token.clone()), |_| None);
|
.map_or(Some(token.clone()), |_| None);
|
||||||
|
@ -200,6 +203,22 @@ impl RegexRule for StyleRule {
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if let Some(start) = start
|
||||||
|
{
|
||||||
|
if let Some(styles) =
|
||||||
|
Styles::from_source(token.source(), &state.shared.lsp)
|
||||||
|
{
|
||||||
|
match index
|
||||||
|
{
|
||||||
|
0 => styles.add(start.start()..token.end(), crate::lsp::styles::Style::Style("bold".into())),
|
||||||
|
1 => styles.add(start.start()..token.end(), crate::lsp::styles::Style::Style("italic".into())),
|
||||||
|
2 => styles.add(start.start()..token.end(), crate::lsp::styles::Style::Style("underlined".into())),
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Style
|
||||||
if let Some((sems, tokens)) = Semantics::from_source(token.source(), &state.shared.lsp)
|
if let Some((sems, tokens)) = Semantics::from_source(token.source(), &state.shared.lsp)
|
||||||
{
|
{
|
||||||
sems.add(token.start()..token.end(), tokens.style_marker);
|
sems.add(token.start()..token.end(), tokens.style_marker);
|
||||||
|
|
|
@ -5,8 +5,6 @@ use std::rc::Rc;
|
||||||
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use tower_lsp::jsonrpc::Request;
|
|
||||||
use tower_lsp::jsonrpc::{self};
|
|
||||||
use tower_lsp::lsp_types::Position;
|
use tower_lsp::lsp_types::Position;
|
||||||
|
|
||||||
use crate::parser::source::LineCursor;
|
use crate::parser::source::LineCursor;
|
||||||
|
|
|
@ -8,6 +8,7 @@ use super::definition::DefinitionData;
|
||||||
use super::hints::HintsData;
|
use super::hints::HintsData;
|
||||||
use super::semantic::SemanticsData;
|
use super::semantic::SemanticsData;
|
||||||
use super::semantic::Tokens;
|
use super::semantic::Tokens;
|
||||||
|
use super::styles::StylesData;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LSPData {
|
pub struct LSPData {
|
||||||
|
@ -16,6 +17,7 @@ pub struct LSPData {
|
||||||
pub inlay_hints: HashMap<Rc<dyn Source>, HintsData>,
|
pub inlay_hints: HashMap<Rc<dyn Source>, HintsData>,
|
||||||
pub definitions: HashMap<Rc<dyn Source>, DefinitionData>,
|
pub definitions: HashMap<Rc<dyn Source>, DefinitionData>,
|
||||||
pub conceals: HashMap<Rc<dyn Source>, ConcealsData>,
|
pub conceals: HashMap<Rc<dyn Source>, ConcealsData>,
|
||||||
|
pub styles: HashMap<Rc<dyn Source>, StylesData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LSPData {
|
impl LSPData {
|
||||||
|
@ -26,6 +28,7 @@ impl LSPData {
|
||||||
inlay_hints: HashMap::new(),
|
inlay_hints: HashMap::new(),
|
||||||
definitions: HashMap::new(),
|
definitions: HashMap::new(),
|
||||||
conceals: HashMap::new(),
|
conceals: HashMap::new(),
|
||||||
|
styles: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,5 +50,9 @@ impl LSPData {
|
||||||
self.conceals
|
self.conceals
|
||||||
.insert(source.clone(), ConcealsData::new(source.clone()));
|
.insert(source.clone(), ConcealsData::new(source.clone()));
|
||||||
}
|
}
|
||||||
|
if !self.styles.contains_key(&source) {
|
||||||
|
self.styles
|
||||||
|
.insert(source.clone(), StylesData::new(source.clone()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,3 +3,4 @@ pub mod definition;
|
||||||
pub mod hints;
|
pub mod hints;
|
||||||
pub mod semantic;
|
pub mod semantic;
|
||||||
pub mod conceal;
|
pub mod conceal;
|
||||||
|
pub mod styles;
|
||||||
|
|
126
src/lsp/styles.rs
Normal file
126
src/lsp/styles.rs
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
use std::{cell::{Ref, RefCell}, ops::Range, rc::Rc};
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use tower_lsp::lsp_types::Position;
|
||||||
|
|
||||||
|
use crate::parser::source::{LineCursor, Source, SourceFile, SourcePosition, VirtualSource};
|
||||||
|
|
||||||
|
use super::data::LSPData;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct StyleParams {
|
||||||
|
pub text_document: tower_lsp::lsp_types::TextDocumentIdentifier,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct StyleInfo {
|
||||||
|
pub range: tower_lsp::lsp_types::Range,
|
||||||
|
pub style: Style,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub enum Style {
|
||||||
|
Color(u32),
|
||||||
|
Style(String),
|
||||||
|
Full {
|
||||||
|
color: u32,
|
||||||
|
style: String,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Per file styles
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct StylesData {
|
||||||
|
/// The styles
|
||||||
|
pub styles: RefCell<Vec<StyleInfo>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StylesData {
|
||||||
|
pub fn new(source: Rc<dyn Source>) -> Self {
|
||||||
|
Self {
|
||||||
|
styles: RefCell::new(vec![]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Temporary data returned by [`Self::from_source_impl`]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Styles<'a> {
|
||||||
|
pub(self) styles: Ref<'a, StylesData>,
|
||||||
|
// The source used when resolving the parent source
|
||||||
|
pub(self) original_source: Rc<dyn Source>,
|
||||||
|
/// The resolved parent source
|
||||||
|
pub(self) source: Rc<dyn Source>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Styles<'a> {
|
||||||
|
fn from_source_impl(
|
||||||
|
source: Rc<dyn Source>,
|
||||||
|
lsp: &'a Option<RefCell<LSPData>>,
|
||||||
|
original_source: Rc<dyn Source>,
|
||||||
|
) -> Option<Self> {
|
||||||
|
if (source.name().starts_with(":LUA:") || source.name().starts_with(":VAR:"))
|
||||||
|
&& source.downcast_ref::<VirtualSource>().is_some()
|
||||||
|
{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(location) = source
|
||||||
|
.clone()
|
||||||
|
.downcast_rc::<VirtualSource>()
|
||||||
|
.ok()
|
||||||
|
.as_ref()
|
||||||
|
.map(|parent| parent.location())
|
||||||
|
.unwrap_or(None)
|
||||||
|
{
|
||||||
|
return Self::from_source_impl(location.source(), lsp, original_source);
|
||||||
|
} else if let Ok(source) = source.clone().downcast_rc::<SourceFile>() {
|
||||||
|
return Ref::filter_map(lsp.as_ref().unwrap().borrow(), |lsp: &LSPData| {
|
||||||
|
lsp.styles.get(&(source.clone() as Rc<dyn Source>))
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
.map(|styles| Self {
|
||||||
|
styles,
|
||||||
|
source,
|
||||||
|
original_source,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_source(source: Rc<dyn Source>, lsp: &'a Option<RefCell<LSPData>>) -> Option<Self> {
|
||||||
|
if lsp.is_none() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Self::from_source_impl(source.clone(), lsp, source)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add(&self, range: Range<usize>, style: Style) {
|
||||||
|
let range = self.original_source.original_range(range).1;
|
||||||
|
let mut cursor = LineCursor::new(self.original_source.clone());
|
||||||
|
cursor.move_to(range.start);
|
||||||
|
|
||||||
|
let line = cursor.line;
|
||||||
|
let start_char = cursor.line_pos;
|
||||||
|
|
||||||
|
cursor.move_to(range.end);
|
||||||
|
assert_eq!(line, cursor.line);
|
||||||
|
let end_char = cursor.line_pos;
|
||||||
|
|
||||||
|
self.styles.styles.borrow_mut().push(StyleInfo {
|
||||||
|
range: tower_lsp::lsp_types::Range {
|
||||||
|
start: Position {
|
||||||
|
line: line as u32,
|
||||||
|
character: start_char as u32,
|
||||||
|
},
|
||||||
|
end: Position {
|
||||||
|
line: line as u32,
|
||||||
|
character: end_char as u32,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
style,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,10 +9,10 @@ mod parser;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use downcast_rs::Downcast;
|
|
||||||
use lsp::conceal::ConcealInfo;
|
use lsp::conceal::ConcealInfo;
|
||||||
use lsp::conceal::ConcealParams;
|
use lsp::conceal::ConcealParams;
|
||||||
use lsp::conceal::ConcealTarget;
|
use lsp::styles::StyleInfo;
|
||||||
|
use lsp::styles::StyleParams;
|
||||||
use parser::langparser::LangParser;
|
use parser::langparser::LangParser;
|
||||||
use parser::parser::ParseMode;
|
use parser::parser::ParseMode;
|
||||||
use parser::parser::Parser;
|
use parser::parser::Parser;
|
||||||
|
@ -35,6 +35,7 @@ struct Backend {
|
||||||
diagnostic_map: DashMap<String, Vec<Diagnostic>>,
|
diagnostic_map: DashMap<String, Vec<Diagnostic>>,
|
||||||
hints_map: DashMap<String, Vec<InlayHint>>,
|
hints_map: DashMap<String, Vec<InlayHint>>,
|
||||||
conceals_map: DashMap<String, Vec<ConcealInfo>>,
|
conceals_map: DashMap<String, Vec<ConcealInfo>>,
|
||||||
|
styles_map: DashMap<String, Vec<StyleInfo>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -72,9 +73,10 @@ impl Backend {
|
||||||
ParseMode::default(),
|
ParseMode::default(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Semantics
|
|
||||||
if let Some(lsp) = state.shared.lsp.as_ref() {
|
if let Some(lsp) = state.shared.lsp.as_ref() {
|
||||||
let borrow = lsp.borrow();
|
let borrow = lsp.borrow();
|
||||||
|
|
||||||
|
// Semantics
|
||||||
for (source, sem) in &borrow.semantic_data {
|
for (source, sem) in &borrow.semantic_data {
|
||||||
if let Some(path) = source
|
if let Some(path) = source
|
||||||
.clone()
|
.clone()
|
||||||
|
@ -86,11 +88,8 @@ impl Backend {
|
||||||
.insert(path, sem.tokens.replace(vec![]));
|
.insert(path, sem.tokens.replace(vec![]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Hints
|
// Inlay hints
|
||||||
if let Some(lsp) = state.shared.lsp.as_ref() {
|
|
||||||
let borrow = lsp.borrow();
|
|
||||||
for (source, hints) in &borrow.inlay_hints {
|
for (source, hints) in &borrow.inlay_hints {
|
||||||
if let Some(path) = source
|
if let Some(path) = source
|
||||||
.clone()
|
.clone()
|
||||||
|
@ -101,11 +100,8 @@ impl Backend {
|
||||||
self.hints_map.insert(path, hints.hints.replace(vec![]));
|
self.hints_map.insert(path, hints.hints.replace(vec![]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Definitions
|
// Definitions
|
||||||
if let Some(lsp) = state.shared.lsp.as_ref() {
|
|
||||||
let borrow = lsp.borrow();
|
|
||||||
for (source, definitions) in &borrow.definitions {
|
for (source, definitions) in &borrow.definitions {
|
||||||
if let Some(path) = source
|
if let Some(path) = source
|
||||||
.clone()
|
.clone()
|
||||||
|
@ -117,11 +113,8 @@ impl Backend {
|
||||||
.insert(path, definitions.definitions.replace(vec![]));
|
.insert(path, definitions.definitions.replace(vec![]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Conceals
|
// Conceals
|
||||||
if let Some(lsp) = state.shared.lsp.as_ref() {
|
|
||||||
let borrow = lsp.borrow();
|
|
||||||
for (source, conceals) in &borrow.conceals {
|
for (source, conceals) in &borrow.conceals {
|
||||||
if let Some(path) = source
|
if let Some(path) = source
|
||||||
.clone()
|
.clone()
|
||||||
|
@ -133,6 +126,19 @@ impl Backend {
|
||||||
.insert(path, conceals.conceals.replace(vec![]));
|
.insert(path, conceals.conceals.replace(vec![]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Styles
|
||||||
|
for (source, styles) in &borrow.styles {
|
||||||
|
if let Some(path) = source
|
||||||
|
.clone()
|
||||||
|
.downcast_rc::<SourceFile>()
|
||||||
|
.ok()
|
||||||
|
.map(|source| source.path().to_owned())
|
||||||
|
{
|
||||||
|
self.styles_map
|
||||||
|
.insert(path, styles.styles.replace(vec![]));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,11 +146,21 @@ impl Backend {
|
||||||
&self,
|
&self,
|
||||||
params: ConcealParams,
|
params: ConcealParams,
|
||||||
) -> jsonrpc::Result<Vec<ConcealInfo>> {
|
) -> jsonrpc::Result<Vec<ConcealInfo>> {
|
||||||
eprintln!("HERE {:#?}", self.conceals_map);
|
|
||||||
if let Some(conceals) = self.conceals_map.get(params.text_document.uri.as_str()) {
|
if let Some(conceals) = self.conceals_map.get(params.text_document.uri.as_str()) {
|
||||||
let (_, data) = conceals.pair();
|
let (_, data) = conceals.pair();
|
||||||
|
|
||||||
eprintln!("HERE2");
|
return Ok(data.to_vec());
|
||||||
|
}
|
||||||
|
Ok(vec![])
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_style_request(
|
||||||
|
&self,
|
||||||
|
params: StyleParams,
|
||||||
|
) -> jsonrpc::Result<Vec<StyleInfo>> {
|
||||||
|
if let Some(styles) = self.styles_map.get(params.text_document.uri.as_str()) {
|
||||||
|
let (_, data) = styles.pair();
|
||||||
|
|
||||||
return Ok(data.to_vec());
|
return Ok(data.to_vec());
|
||||||
}
|
}
|
||||||
Ok(vec![])
|
Ok(vec![])
|
||||||
|
@ -357,8 +373,10 @@ async fn main() {
|
||||||
diagnostic_map: DashMap::new(),
|
diagnostic_map: DashMap::new(),
|
||||||
hints_map: DashMap::new(),
|
hints_map: DashMap::new(),
|
||||||
conceals_map: DashMap::new(),
|
conceals_map: DashMap::new(),
|
||||||
|
styles_map: DashMap::new(),
|
||||||
})
|
})
|
||||||
.custom_method("textDocument/conceal", Backend::handle_conceal_request)
|
.custom_method("textDocument/conceal", Backend::handle_conceal_request)
|
||||||
|
.custom_method("textDocument/style", Backend::handle_style_request)
|
||||||
.finish();
|
.finish();
|
||||||
|
|
||||||
Server::new(stdin, stdout, socket).serve(service).await;
|
Server::new(stdin, stdout, socket).serve(service).await;
|
||||||
|
|
Loading…
Reference in a new issue