allow stdin input to statix-single, vim plugin

This commit is contained in:
Akshay 2021-10-27 17:10:42 +05:30
parent ed1ee66b06
commit f909b20c54
8 changed files with 69 additions and 25 deletions

View File

@ -1,6 +1,6 @@
[package]
name = "statix"
version = "0.2.0"
version = "0.2.2"
edition = "2018"
license = "MIT"

View File

@ -77,8 +77,8 @@ impl Fix {
#[derive(Clap, Debug)]
pub struct Single {
/// File to run single-fix on
#[clap(default_value = ".", parse(from_os_str))]
pub target: PathBuf,
#[clap(parse(from_os_str))]
pub target: Option<PathBuf>,
/// Position to attempt a fix at
#[clap(short, long, parse(try_from_str = parse_line_col))]

View File

@ -15,7 +15,7 @@ fn pos_to_byte(line: usize, col: usize, src: &str) -> Result<TextSize, SingleFix
for (l, _) in src
.split_inclusive('\n')
.zip(1..)
.take_while(|(_, i)| i < &line)
.take_while(|(_, i)| *i < line)
{
byte += TextSize::of(l);
}
@ -29,7 +29,6 @@ fn pos_to_byte(line: usize, col: usize, src: &str) -> Result<TextSize, SingleFix
}
fn find(offset: TextSize, src: &str) -> Result<Report, SingleFixErr> {
let offset = offset - TextSize::from(1u32);
// we don't really need the source to form a completely parsed tree
let parsed = rnix::parse(src);
@ -38,22 +37,18 @@ fn find(offset: TextSize, src: &str) -> Result<Report, SingleFixErr> {
.preorder_with_tokens()
.filter_map(|event| match event {
WalkEvent::Enter(child) => {
if child.text_range().start() == offset {
LINTS.get(&child.kind()).map(|rules| {
rules
.iter()
.filter_map(|rule| rule.validate(&child))
.filter(|report| report.total_suggestion_range().is_some())
.next()
})
} else {
None
}
LINTS.get(&child.kind()).map(|rules| {
rules
.iter()
.filter_map(|rule| rule.validate(&child))
.filter(|report| report.total_suggestion_range().is_some())
.next()
})
}
_ => None,
})
.flatten()
.next()
.find(|report| report.total_diagnostic_range().unwrap().contains(offset))
.ok_or(SingleFixErr::NoOp)
}

View File

@ -4,7 +4,7 @@ mod fix;
mod lint;
mod traits;
use std::io;
use std::io::{self, BufRead};
use crate::{
err::{FixErr, SingleFixErr, StatixErr},
@ -55,15 +55,26 @@ fn _main() -> Result<(), StatixErr> {
}
}
}
// FIXME: this block nasty, configure in/out streams in `impl Single` maybe
SubCommand::Single(single_config) => {
let path = single_config.target;
let src = std::fs::read_to_string(&path).map_err(SingleFixErr::InvalidPath)?;
let src = if let Some(path) = &single_config.target {
std::fs::read_to_string(&path).map_err(SingleFixErr::InvalidPath)?
} else {
io::stdin().lock().lines().map(|l| l.unwrap()).collect::<Vec<String>>().join("\n")
};
let path_id = if let Some(path) = &single_config.target {
path.display().to_string()
} else {
"<unknown>".to_owned()
};
let (line, col) = single_config.position;
let single_fix_result = fix::single(line, col, &src)?;
if single_config.diff_only {
let text_diff = TextDiff::from_lines(src.as_str(), &single_fix_result.src);
let old_file = format!("{}", path.display());
let new_file = format!("{} [fixed]", path.display());
let old_file = format!("{}", path_id);
let new_file = format!("{} [fixed]", path_id);
println!(
"{}",
text_diff
@ -71,9 +82,11 @@ fn _main() -> Result<(), StatixErr> {
.context_radius(4)
.header(&old_file, &new_file)
);
} else {
} else if let Some(path) = single_config.target {
std::fs::write(&path, &*single_fix_result.src)
.map_err(SingleFixErr::InvalidPath)?;
} else {
print!("{}", &*single_fix_result.src)
}
}
}

View File

@ -49,7 +49,7 @@
statix = with final; pkgs.stdenv.mkDerivation {
pname = "statix";
version = "v0.2.0";
version = "v0.2.2";
src = builtins.path {
path = ./.;
name = "statix";
@ -75,10 +75,17 @@
};
};
statix-vim =
with final; pkgs.vimUtils.buildVimPlugin {
pname = "statix-vim";
version = "0.1.0";
src = ./vim-plugin;
};
};
packages = forAllSystems (system: {
inherit (nixpkgsFor."${system}") statix;
inherit (nixpkgsFor."${system}") statix statix-vim;
});
defaultPackage =

View File

@ -56,6 +56,13 @@ impl Report {
.flat_map(|d| Some(d.suggestion.as_ref()?.at))
.reduce(|acc, next| acc.cover(next))
}
/// A range that encompasses all the diagnostics provided in this report
pub fn total_diagnostic_range(&self) -> Option<TextRange> {
self.diagnostics
.iter()
.flat_map(|d| Some(d.at))
.reduce(|acc, next| acc.cover(next))
}
/// Unsafe but handy replacement for above
pub fn range(&self) -> TextRange {
self.total_suggestion_range().unwrap()

View File

@ -0,0 +1,8 @@
setlocal makeprg=statix\ check\ -o\ errfmt\ %
setlocal errorformat=%f>%l:%c:%t:%n:%m
augroup StatixCheck
autocmd!
autocmd! BufWritePost *.nix | silent make! | silent redraw!
autocmd QuickFixCmdPost [^l]* cwindow
augroup END

View File

@ -0,0 +1,14 @@
function! ApplyStatixSuggestion()
let l:l = line('.')
let l:c = col('.')
let l:filter = "%!statix single -p " . l . "," . c . ""
execute l:filter
silent if v:shell_error == 1
undo
endif
call cursor(l, c)
endfunction
nnoremap gf :call ApplyStatixSuggestion()<cr>