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::Scope;
|
||||
use ariadne::Fmt;
|
||||
use lsp::styles::Styles;
|
||||
use mlua::Function;
|
||||
use regex::Captures;
|
||||
use regex::Regex;
|
||||
|
@ -188,6 +189,8 @@ impl RegexRule for StyleRule {
|
|||
};
|
||||
|
||||
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]
|
||||
.clone()
|
||||
.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)
|
||||
{
|
||||
sems.add(token.start()..token.end(), tokens.style_marker);
|
||||
|
|
|
@ -5,8 +5,6 @@ use std::rc::Rc;
|
|||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use tower_lsp::jsonrpc::Request;
|
||||
use tower_lsp::jsonrpc::{self};
|
||||
use tower_lsp::lsp_types::Position;
|
||||
|
||||
use crate::parser::source::LineCursor;
|
||||
|
|
|
@ -8,6 +8,7 @@ use super::definition::DefinitionData;
|
|||
use super::hints::HintsData;
|
||||
use super::semantic::SemanticsData;
|
||||
use super::semantic::Tokens;
|
||||
use super::styles::StylesData;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LSPData {
|
||||
|
@ -16,6 +17,7 @@ pub struct LSPData {
|
|||
pub inlay_hints: HashMap<Rc<dyn Source>, HintsData>,
|
||||
pub definitions: HashMap<Rc<dyn Source>, DefinitionData>,
|
||||
pub conceals: HashMap<Rc<dyn Source>, ConcealsData>,
|
||||
pub styles: HashMap<Rc<dyn Source>, StylesData>,
|
||||
}
|
||||
|
||||
impl LSPData {
|
||||
|
@ -26,6 +28,7 @@ impl LSPData {
|
|||
inlay_hints: HashMap::new(),
|
||||
definitions: HashMap::new(),
|
||||
conceals: HashMap::new(),
|
||||
styles: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,5 +50,9 @@ impl LSPData {
|
|||
self.conceals
|
||||
.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 semantic;
|
||||
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 dashmap::DashMap;
|
||||
use downcast_rs::Downcast;
|
||||
use lsp::conceal::ConcealInfo;
|
||||
use lsp::conceal::ConcealParams;
|
||||
use lsp::conceal::ConcealTarget;
|
||||
use lsp::styles::StyleInfo;
|
||||
use lsp::styles::StyleParams;
|
||||
use parser::langparser::LangParser;
|
||||
use parser::parser::ParseMode;
|
||||
use parser::parser::Parser;
|
||||
|
@ -35,6 +35,7 @@ struct Backend {
|
|||
diagnostic_map: DashMap<String, Vec<Diagnostic>>,
|
||||
hints_map: DashMap<String, Vec<InlayHint>>,
|
||||
conceals_map: DashMap<String, Vec<ConcealInfo>>,
|
||||
styles_map: DashMap<String, Vec<StyleInfo>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -72,9 +73,10 @@ impl Backend {
|
|||
ParseMode::default(),
|
||||
);
|
||||
|
||||
// Semantics
|
||||
if let Some(lsp) = state.shared.lsp.as_ref() {
|
||||
let borrow = lsp.borrow();
|
||||
|
||||
// Semantics
|
||||
for (source, sem) in &borrow.semantic_data {
|
||||
if let Some(path) = source
|
||||
.clone()
|
||||
|
@ -86,11 +88,8 @@ impl Backend {
|
|||
.insert(path, sem.tokens.replace(vec![]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hints
|
||||
if let Some(lsp) = state.shared.lsp.as_ref() {
|
||||
let borrow = lsp.borrow();
|
||||
// Inlay hints
|
||||
for (source, hints) in &borrow.inlay_hints {
|
||||
if let Some(path) = source
|
||||
.clone()
|
||||
|
@ -101,11 +100,8 @@ impl Backend {
|
|||
self.hints_map.insert(path, hints.hints.replace(vec![]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Definitions
|
||||
if let Some(lsp) = state.shared.lsp.as_ref() {
|
||||
let borrow = lsp.borrow();
|
||||
// Definitions
|
||||
for (source, definitions) in &borrow.definitions {
|
||||
if let Some(path) = source
|
||||
.clone()
|
||||
|
@ -117,11 +113,8 @@ impl Backend {
|
|||
.insert(path, definitions.definitions.replace(vec![]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Conceals
|
||||
if let Some(lsp) = state.shared.lsp.as_ref() {
|
||||
let borrow = lsp.borrow();
|
||||
// Conceals
|
||||
for (source, conceals) in &borrow.conceals {
|
||||
if let Some(path) = source
|
||||
.clone()
|
||||
|
@ -133,6 +126,19 @@ impl Backend {
|
|||
.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,
|
||||
params: ConcealParams,
|
||||
) -> jsonrpc::Result<Vec<ConcealInfo>> {
|
||||
eprintln!("HERE {:#?}", self.conceals_map);
|
||||
if let Some(conceals) = self.conceals_map.get(params.text_document.uri.as_str()) {
|
||||
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());
|
||||
}
|
||||
Ok(vec![])
|
||||
|
@ -357,8 +373,10 @@ async fn main() {
|
|||
diagnostic_map: DashMap::new(),
|
||||
hints_map: DashMap::new(),
|
||||
conceals_map: DashMap::new(),
|
||||
styles_map: DashMap::new(),
|
||||
})
|
||||
.custom_method("textDocument/conceal", Backend::handle_conceal_request)
|
||||
.custom_method("textDocument/style", Backend::handle_style_request)
|
||||
.finish();
|
||||
|
||||
Server::new(stdin, stdout, socket).serve(service).await;
|
||||
|
|
Loading…
Reference in a new issue