Refactor workspace commands

This commit is contained in:
Patrick Förster 2023-04-14 21:25:15 +02:00
parent 9d1f57891d
commit 418ba1907e
17 changed files with 293 additions and 269 deletions

View file

@ -0,0 +1,21 @@
[package]
name = "commands"
version = "0.0.0"
license.workspace = true
authors.workspace = true
edition.workspace = true
rust-version.workspace = true
[dependencies]
anyhow = "1.0.70"
base-db = { path = "../base-db" }
base-feature = { path = "../base-feature" }
itertools = "0.10.5"
log = "0.4.17"
rowan = "0.15.11"
rustc-hash = "1.1.0"
syntax = { path = "../syntax" }
url = "2.3.1"
[lib]
doctest = false

View file

@ -0,0 +1,40 @@
use base_db::Document;
use rowan::{ast::AstNode, TextRange, TextSize};
use syntax::latex;
#[derive(Debug)]
pub struct ChangeEnvironmentResult<'a> {
pub begin: TextRange,
pub end: TextRange,
pub old_name: String,
pub new_name: &'a str,
}
pub fn change_environment<'a>(
document: &'a Document,
position: TextSize,
new_name: &'a str,
) -> Option<ChangeEnvironmentResult<'a>> {
let root = document.data.as_tex()?.root_node();
let environment = root
.token_at_offset(position)
.right_biased()?
.parent_ancestors()
.find_map(latex::Environment::cast)?;
let begin = environment.begin()?.name()?.key()?;
let end = environment.end()?.name()?.key()?;
let old_name = begin.to_string();
if old_name != end.to_string() {
return None;
}
Some(ChangeEnvironmentResult {
begin: latex::small_range(&begin),
end: latex::small_range(&end),
old_name,
new_name,
})
}

View file

@ -0,0 +1,57 @@
use std::process::Stdio;
use anyhow::Result;
use base_db::{Document, Workspace};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
pub enum CleanTarget {
Auxiliary,
Artifacts,
}
#[derive(Debug)]
pub struct CleanCommand {
executable: String,
args: Vec<String>,
}
impl CleanCommand {
pub fn new(workspace: &Workspace, document: &Document, target: CleanTarget) -> Result<Self> {
let Some(path) = document.path.as_deref() else {
anyhow::bail!("document '{}' is not a local file", document.uri)
};
let dir = workspace.current_dir(&document.dir);
let dir = workspace.output_dir(&dir).to_file_path().unwrap();
let flag = match target {
CleanTarget::Auxiliary => "-c",
CleanTarget::Artifacts => "-C",
};
let executable = String::from("latexmk");
let args = vec![
format!("-outdir={}", dir.display()),
String::from(flag),
path.display().to_string(),
];
Ok(Self { executable, args })
}
pub fn run(self) -> Result<()> {
log::debug!("Cleaning output files: {} {:?}", self.executable, self.args);
let result = std::process::Command::new(self.executable)
.args(self.args)
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
.status();
if let Err(why) = result {
anyhow::bail!("failed to spawn process: {why}")
}
Ok(())
}
}

View file

@ -0,0 +1,57 @@
use std::io::Write;
use anyhow::Result;
use base_db::{graph, Document, Workspace};
use itertools::Itertools;
use rustc_hash::FxHashMap;
pub fn show_dependency_graph(workspace: &Workspace) -> Result<String> {
let documents = workspace
.iter()
.enumerate()
.map(|(i, doc)| (doc, format!("v{i:0>5}")))
.collect::<FxHashMap<&Document, String>>();
let mut writer = Vec::new();
writeln!(&mut writer, "digraph G {{")?;
writeln!(&mut writer, "rankdir = LR;")?;
for (document, node) in &documents {
let label = document.uri.as_str();
let shape = if document
.data
.as_tex()
.map_or(false, |data| data.semantics.can_be_root)
{
"tripleoctagon"
} else if document
.data
.as_tex()
.map_or(false, |data| data.semantics.can_be_compiled)
{
"doubleoctagon"
} else {
"octagon"
};
writeln!(&mut writer, "\t{node} [label=\"{label}\", shape={shape}];")?;
}
for edge in workspace
.iter()
.flat_map(|start| graph::Graph::new(workspace, start).edges)
.unique()
{
let source = &documents[edge.source];
let target = &documents[edge.target];
let label = edge
.weight
.as_ref()
.map_or("<artifact>", |weight| &weight.link.path.text);
writeln!(&mut writer, "\t{source} -> {target} [label=\"{label}\"];")?;
}
writeln!(&mut writer, "}}")?;
Ok(String::from_utf8(writer)?)
}

View file

@ -0,0 +1,5 @@
mod change_env;
mod clean;
mod dep_graph;
pub use self::{change_env::*, clean::*, dep_graph::*};