mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-22 10:57:30 +08:00
Teach fish_indent to only indent and unindent
To be used in the following commits.
This commit is contained in:
parent
7369516871
commit
47a446ae18
|
@ -25,6 +25,12 @@ The following options are available:
|
|||
**-i** or **--no-indent**
|
||||
Do not indent commands; only reformat to one job per line.
|
||||
|
||||
**--only-indent**
|
||||
Do not reformat, only indent each line.
|
||||
|
||||
**--only-unindent**
|
||||
Do not reformat, only unindent each line.
|
||||
|
||||
**-c** or **--check**
|
||||
Do not indent, only return 0 if the code is already indented as fish_indent would, the number of failed files otherwise. Also print the failed filenames if not reading from standard input.
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
complete -c fish_indent -s h -l help -d 'Display help and exit'
|
||||
complete -c fish_indent -s v -l version -d 'Display version and exit'
|
||||
complete -c fish_indent -s i -l no-indent -d 'Do not indent output, only reformat into one job per line'
|
||||
complete -c fish_indent -l only-indent -d 'Do not reformat, only indent lines'
|
||||
complete -c fish_indent -l only-unindent -d 'Do not reformat, only unindent lines'
|
||||
complete -c fish_indent -l ansi -d 'Colorize the output using ANSI escape sequences'
|
||||
complete -c fish_indent -l html -d 'Output in HTML format'
|
||||
complete -c fish_indent -s w -l write -d 'Write to file'
|
||||
|
|
|
@ -36,7 +36,7 @@ use fish::highlight::{colorize, highlight_shell, HighlightRole, HighlightSpec};
|
|||
use fish::libc::setlinebuf;
|
||||
use fish::operation_context::OperationContext;
|
||||
use fish::parse_constants::{ParseTokenType, ParseTreeFlags, SourceRange};
|
||||
use fish::parse_util::parse_util_compute_indents;
|
||||
use fish::parse_util::{apply_indents, parse_util_compute_indents, SPACES_PER_INDENT};
|
||||
use fish::print_help::print_help;
|
||||
use fish::printf;
|
||||
use fish::threads;
|
||||
|
@ -52,10 +52,6 @@ use fish::{
|
|||
future_feature_flags,
|
||||
};
|
||||
|
||||
// The number of spaces per indent isn't supposed to be configurable.
|
||||
// See discussion at https://github.com/fish-shell/fish-shell/pull/6790
|
||||
const SPACES_PER_INDENT: usize = 4;
|
||||
|
||||
/// Note: this got somewhat more complicated after introducing the new AST, because that AST no
|
||||
/// longer encodes detailed lexical information (e.g. every newline). This feels more complex
|
||||
/// than necessary and would probably benefit from a more layered approach where we identify
|
||||
|
@ -777,6 +773,8 @@ fn throwing_main() -> i32 {
|
|||
let mut output_type = OutputType::PlainText;
|
||||
let mut output_location = L!("");
|
||||
let mut do_indent = true;
|
||||
let mut only_indent = false;
|
||||
let mut only_unindent = false;
|
||||
// File path for debug output.
|
||||
let mut debug_output = None;
|
||||
|
||||
|
@ -795,6 +793,8 @@ fn throwing_main() -> i32 {
|
|||
),
|
||||
wopt(L!("dump-parse-tree"), woption_argument_t::no_argument, 'P'),
|
||||
wopt(L!("no-indent"), woption_argument_t::no_argument, 'i'),
|
||||
wopt(L!("only-indent"), woption_argument_t::no_argument, '\x04'),
|
||||
wopt(L!("only-unindent"), woption_argument_t::no_argument, '\x05'),
|
||||
wopt(L!("help"), woption_argument_t::no_argument, 'h'),
|
||||
wopt(L!("version"), woption_argument_t::no_argument, 'v'),
|
||||
wopt(L!("write"), woption_argument_t::no_argument, 'w'),
|
||||
|
@ -830,6 +830,8 @@ fn throwing_main() -> i32 {
|
|||
}
|
||||
'w' => output_type = OutputType::File,
|
||||
'i' => do_indent = false,
|
||||
'\x04' => only_indent = true,
|
||||
'\x05' => only_unindent = true,
|
||||
'\x01' => output_type = OutputType::Html,
|
||||
'\x02' => output_type = OutputType::Ansi,
|
||||
'\x03' => output_type = OutputType::PygmentsCsv,
|
||||
|
@ -920,7 +922,45 @@ fn throwing_main() -> i32 {
|
|||
continue;
|
||||
}
|
||||
|
||||
let output_wtext = prettify(&src, do_indent);
|
||||
let output_wtext = if only_indent || only_unindent {
|
||||
let indents = parse_util_compute_indents(&src);
|
||||
if only_indent {
|
||||
apply_indents(&src, &indents)
|
||||
} else {
|
||||
// Only unindent.
|
||||
let mut indented_everywhere = true;
|
||||
for (i, c) in src.chars().enumerate() {
|
||||
if c != '\n' || i + 1 == src.len() {
|
||||
continue;
|
||||
}
|
||||
let num_spaces = SPACES_PER_INDENT * usize::try_from(indents[i + 1]).unwrap();
|
||||
if src.len() < i + 1 + num_spaces
|
||||
|| !src[i + 1..].chars().take(num_spaces).all(|c| c == ' ')
|
||||
{
|
||||
indented_everywhere = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if indented_everywhere {
|
||||
let mut out = WString::new();
|
||||
let mut i = 0;
|
||||
while i < src.len() {
|
||||
let c = src.as_char_slice()[i];
|
||||
out.push(c);
|
||||
i += 1;
|
||||
if c != '\n' || i == src.len() {
|
||||
continue;
|
||||
}
|
||||
i += SPACES_PER_INDENT * usize::try_from(indents[i]).unwrap();
|
||||
}
|
||||
out
|
||||
} else {
|
||||
src.clone()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
prettify(&src, do_indent)
|
||||
};
|
||||
|
||||
// Maybe colorize.
|
||||
let mut colors = vec![];
|
||||
|
|
|
@ -798,6 +798,24 @@ pub fn parse_util_compute_indents(src: &wstr) -> Vec<i32> {
|
|||
indents
|
||||
}
|
||||
|
||||
// The number of spaces per indent isn't supposed to be configurable.
|
||||
// See discussion at https://github.com/fish-shell/fish-shell/pull/6790
|
||||
pub const SPACES_PER_INDENT: usize = 4;
|
||||
|
||||
pub fn apply_indents(src: &wstr, indents: &[i32]) -> WString {
|
||||
let mut indented = WString::new();
|
||||
for (i, c) in src.chars().enumerate() {
|
||||
indented.push(c);
|
||||
if c != '\n' || i + 1 == src.len() {
|
||||
continue;
|
||||
}
|
||||
indented.extend(
|
||||
std::iter::repeat(' ').take(SPACES_PER_INDENT * usize::try_from(indents[i]).unwrap()),
|
||||
);
|
||||
}
|
||||
indented
|
||||
}
|
||||
|
||||
// Visit all of our nodes. When we get a job_list or case_item_list, increment indent while
|
||||
// visiting its children.
|
||||
struct IndentVisitor<'a> {
|
||||
|
@ -962,7 +980,12 @@ impl<'a> NodeVisitor<'a> for IndentVisitor<'a> {
|
|||
|
||||
// If this is a leaf node, apply the current indentation.
|
||||
if node.category() == Category::leaf && range.length() != 0 {
|
||||
self.indents[range.start()..range.end()].fill(self.indent);
|
||||
let leading_spaces = self.src[..range.start()]
|
||||
.chars()
|
||||
.rev()
|
||||
.take_while(|&c| c == ' ')
|
||||
.count();
|
||||
self.indents[range.start() - leading_spaces..range.end()].fill(self.indent);
|
||||
self.last_leaf_end = range.end();
|
||||
self.last_indent = self.indent;
|
||||
}
|
||||
|
|
|
@ -85,6 +85,7 @@ use crate::pager::{PageRendering, Pager, SelectionMotion};
|
|||
use crate::parse_constants::SourceRange;
|
||||
use crate::parse_constants::{ParseTreeFlags, ParserTestErrorBits};
|
||||
use crate::parse_tree::ParsedSource;
|
||||
use crate::parse_util::SPACES_PER_INDENT;
|
||||
use crate::parse_util::{
|
||||
parse_util_cmdsubst_extent, parse_util_compute_indents, parse_util_contains_wildcards,
|
||||
parse_util_detect_errors, parse_util_detect_errors_in_ast, parse_util_escape_string_with_quote,
|
||||
|
@ -2789,7 +2790,9 @@ impl ReaderData {
|
|||
let total_offset_new = parse_util_get_offset(
|
||||
el.text(),
|
||||
line_new,
|
||||
line_offset_old - 4 * (indent_new - indent_old),
|
||||
line_offset_old
|
||||
- isize::try_from(SPACES_PER_INDENT).unwrap()
|
||||
* (indent_new - indent_old),
|
||||
);
|
||||
self.update_buff_pos(elt, total_offset_new);
|
||||
}
|
||||
|
|
|
@ -464,3 +464,35 @@ echo "
|
|||
echo this file starts late
|
||||
" | $fish_indent
|
||||
#CHECK: echo this file starts late
|
||||
|
||||
echo 'foo|bar; begin
|
||||
echo' | $fish_indent --only-indent
|
||||
# CHECK: foo|bar; begin
|
||||
# CHECK: {{^}} echo
|
||||
|
||||
echo 'begin
|
||||
echo
|
||||
end' | $fish_indent --only-unindent
|
||||
# CHECK: {{^}}begin
|
||||
# CHECK: {{^}}echo
|
||||
# CHECK: {{^}}end
|
||||
|
||||
echo 'if true
|
||||
begin
|
||||
echo
|
||||
end
|
||||
end' | $fish_indent --only-unindent
|
||||
# CHECK: {{^}}if true
|
||||
# CHECK: {{^}}begin
|
||||
# CHECK: {{^}}echo
|
||||
# CHECK: {{^}}end
|
||||
# CHECK: {{^}}end
|
||||
|
||||
echo 'begin
|
||||
echo
|
||||
not indented properly
|
||||
end' | $fish_indent --only-unindent
|
||||
# CHECK: {{^}}begin
|
||||
# CHECK: {{^}} echo
|
||||
# CHECK: {{^}} not indented properly
|
||||
# CHECK: {{^}}end
|
||||
|
|
Loading…
Reference in New Issue
Block a user