mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-22 10:06:49 +08:00
Indent escaped newlines
Similar to what fish_indent does. After typing "echo \" and hitting return, the cursor will be indented. A possible annoyance is that when you have multiple indented lines echo 1 \ 2 \ 3 \ 4 \ If you remove lines in the middle with Control-k, the lines below the deleted one will start jumping around, as they are disconnected from and reconnected to "echo".
This commit is contained in:
parent
511747d59e
commit
5e8a248758
|
@ -272,6 +272,7 @@ Interactive improvements
|
|||
- fish is now more resilient against broken terminal modes (:issue:`7133`, :issue:`4873`).
|
||||
- fish handles being in control of the TTY without owning its own process group better, avoiding some hangs in special configurations (:issue:`7388`).
|
||||
- Keywords can now be colored differently by setting the ``fish_color_keyword`` variable (but ``fish_color_command`` will still be used if it is unset) (:issue:`7678`).
|
||||
- Just like new ``fish_indent``, the interactive reader will indent continuation lines that follow a line ending in a backslash, ``|``, ``&&`` or ``||`` (:issue:`7694`).
|
||||
|
||||
New or improved bindings
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -1451,6 +1451,60 @@ static void test_indents() {
|
|||
1, "\n" //
|
||||
);
|
||||
|
||||
// Continuation lines.
|
||||
add_test(&tests, //
|
||||
0, "echo 'continuation line' \\", //
|
||||
1, "\ncont", //
|
||||
0, "\n" //
|
||||
);
|
||||
add_test(&tests, //
|
||||
0, "echo 'empty continuation line' \\", //
|
||||
1, "\n" //
|
||||
);
|
||||
add_test(&tests, //
|
||||
0, "begin # continuation line in block", //
|
||||
1, "\necho \\", //
|
||||
2, "\ncont" //
|
||||
);
|
||||
add_test(&tests, //
|
||||
0, "begin # empty continuation line in block", //
|
||||
1, "\necho \\", //
|
||||
2, "\n", //
|
||||
0, "\nend" //
|
||||
);
|
||||
add_test(&tests, //
|
||||
0, "echo 'multiple continuation lines' \\", //
|
||||
1, "\nline1 \\", //
|
||||
1, "\n# comment", //
|
||||
1, "\n# more comment", //
|
||||
1, "\nline2 \\", //
|
||||
1, "\n" //
|
||||
);
|
||||
add_test(&tests, //
|
||||
0, "echo # comment ending in \\", //
|
||||
0, "\nline" //
|
||||
);
|
||||
add_test(&tests, //
|
||||
0, "echo 'multiple empty continuation lines' \\", //
|
||||
1, "\n\\", //
|
||||
1, "\n", //
|
||||
0, "\n" //
|
||||
);
|
||||
add_test(&tests, //
|
||||
0, "echo 'multiple statements with continuation lines' \\", //
|
||||
1, "\nline 1", //
|
||||
0, "\necho \\", //
|
||||
1, "\n" //
|
||||
);
|
||||
// This is an edge case, probably okay to change the behavior here.
|
||||
add_test(&tests, //
|
||||
0, "begin", 1, " \\", //
|
||||
2, "\necho 'continuation line in block header' \\", //
|
||||
2, "\n", //
|
||||
1, "\n", //
|
||||
0, "\nend" //
|
||||
);
|
||||
|
||||
int test_idx = 0;
|
||||
for (const test_t &test : tests) {
|
||||
// Construct the input text and expected indents.
|
||||
|
|
|
@ -679,6 +679,7 @@ std::vector<int> parse_util_compute_indents(const wcstring &src) {
|
|||
|
||||
auto range = node.source_range();
|
||||
if (range.length > 0 && node.category == category_t::leaf) {
|
||||
record_line_continuations_until(range.start);
|
||||
std::fill(indents.begin() + last_leaf_end, indents.begin() + range.start,
|
||||
last_indent);
|
||||
}
|
||||
|
@ -714,6 +715,21 @@ std::vector<int> parse_util_compute_indents(const wcstring &src) {
|
|||
return nls.source(src).find(L'\n') != wcstring::npos;
|
||||
}
|
||||
|
||||
void record_line_continuations_until(size_t offset) {
|
||||
wcstring gap_text = src.substr(last_leaf_end, offset - last_leaf_end);
|
||||
size_t escaped_nl = gap_text.find(L"\\\n");
|
||||
if (escaped_nl == wcstring::npos) return;
|
||||
auto end = src.begin() + offset;
|
||||
auto newline = src.begin() + last_leaf_end + escaped_nl + 1;
|
||||
// The gap text might contain multiple newlines if there are multiple lines that
|
||||
// don't contain an AST node, for example, comment lines, or lines containing only
|
||||
// the escaped newline.
|
||||
do {
|
||||
line_continuations.push_back(newline - src.begin());
|
||||
newline = std::find(newline + 1, end, L'\n');
|
||||
} while (newline != end);
|
||||
}
|
||||
|
||||
// The one-past-the-last index of the most recently encountered leaf node.
|
||||
// We use this to populate the indents even if there's no tokens in the range.
|
||||
size_t last_leaf_end{0};
|
||||
|
@ -730,10 +746,14 @@ std::vector<int> parse_util_compute_indents(const wcstring &src) {
|
|||
// Initialize our starting indent to -1, as our top-level node is a job list which
|
||||
// will immediately increment it.
|
||||
int indent{-1};
|
||||
|
||||
// List of locations of escaped newline characters.
|
||||
std::vector<size_t> line_continuations;
|
||||
};
|
||||
|
||||
indent_visitor_t iv(src, indents);
|
||||
node_visitor(iv).accept(ast.top());
|
||||
iv.record_line_continuations_until(indents.size());
|
||||
std::fill(indents.begin() + iv.last_leaf_end, indents.end(), iv.last_indent);
|
||||
|
||||
// All newlines now get the *next* indent.
|
||||
|
@ -755,6 +775,13 @@ std::vector<int> parse_util_compute_indents(const wcstring &src) {
|
|||
next_indent = indents.at(idx);
|
||||
}
|
||||
}
|
||||
// Add an extra level of indentation to continuation lines.
|
||||
for (size_t idx : iv.line_continuations) {
|
||||
do {
|
||||
indents.at(idx)++;
|
||||
} while (++idx < src_size && src.at(idx) != L'\n');
|
||||
}
|
||||
|
||||
return indents;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user