Added -j flag to 'complete' for completing job names/pids
This commit is contained in:
@@ -6,7 +6,7 @@ use tempfile::TempDir;
|
||||
|
||||
use crate::prompt::readline::complete::Completer;
|
||||
use crate::prompt::readline::markers;
|
||||
use crate::state::{write_logic, write_vars, VarFlags};
|
||||
use crate::state::{VarFlags, write_logic, write_vars};
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -192,10 +192,12 @@ fn complete_filename_with_slash() {
|
||||
|
||||
// Should complete files in subdir/
|
||||
if result.is_some() {
|
||||
assert!(completer
|
||||
.candidates
|
||||
.iter()
|
||||
.any(|c| c.contains("nested.txt")));
|
||||
assert!(
|
||||
completer
|
||||
.candidates
|
||||
.iter()
|
||||
.any(|c| c.contains("nested.txt"))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -702,10 +704,12 @@ fn complete_special_characters_in_filename() {
|
||||
|
||||
if result.is_some() {
|
||||
// Should handle special chars in filenames
|
||||
assert!(completer
|
||||
.candidates
|
||||
.iter()
|
||||
.any(|c| c.contains("file-with-dash") || c.contains("file_with_underscore")));
|
||||
assert!(
|
||||
completer
|
||||
.candidates
|
||||
.iter()
|
||||
.any(|c| c.contains("file-with-dash") || c.contains("file_with_underscore"))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,8 +58,8 @@ fn unclosed_squote() {
|
||||
#[test]
|
||||
fn unclosed_brc_grp() {
|
||||
let input = "{ foo bar";
|
||||
let tokens = LexStream::new(Arc::new(input.into()), LexFlags::empty())
|
||||
.collect::<ShResult<Vec<_>>>();
|
||||
let tokens =
|
||||
LexStream::new(Arc::new(input.into()), LexFlags::empty()).collect::<ShResult<Vec<_>>>();
|
||||
|
||||
let Err(err) = tokens else {
|
||||
panic!("Expected an error, got {:?}", tokens);
|
||||
|
||||
@@ -9,7 +9,13 @@ use super::*;
|
||||
#[test]
|
||||
fn simple_expansion() {
|
||||
let varsub = "$foo";
|
||||
write_vars(|v| v.set_var("foo", VarKind::Str("this is the value of the variable".into()), VarFlags::NONE));
|
||||
write_vars(|v| {
|
||||
v.set_var(
|
||||
"foo",
|
||||
VarKind::Str("this is the value of the variable".into()),
|
||||
VarFlags::NONE,
|
||||
)
|
||||
});
|
||||
|
||||
let mut tokens: Vec<Tk> = LexStream::new(Arc::new(varsub.to_string()), LexFlags::empty())
|
||||
.map(|tk| tk.unwrap())
|
||||
@@ -308,7 +314,10 @@ fn dquote_escape_dollar() {
|
||||
fn dquote_escape_backslash() {
|
||||
// "\\" in double quotes should produce a single backslash
|
||||
let result = unescape_str(r#""\\""#);
|
||||
let inner: String = result.chars().filter(|&c| c != markers::DUB_QUOTE).collect();
|
||||
let inner: String = result
|
||||
.chars()
|
||||
.filter(|&c| c != markers::DUB_QUOTE)
|
||||
.collect();
|
||||
assert_eq!(
|
||||
inner, "\\",
|
||||
"Double backslash should produce single backslash"
|
||||
@@ -319,7 +328,10 @@ fn dquote_escape_backslash() {
|
||||
fn dquote_escape_quote() {
|
||||
// "\"" should produce a literal double quote
|
||||
let result = unescape_str(r#""\"""#);
|
||||
let inner: String = result.chars().filter(|&c| c != markers::DUB_QUOTE).collect();
|
||||
let inner: String = result
|
||||
.chars()
|
||||
.filter(|&c| c != markers::DUB_QUOTE)
|
||||
.collect();
|
||||
assert!(
|
||||
inner.contains('"'),
|
||||
"Escaped quote should produce literal quote"
|
||||
@@ -330,7 +342,10 @@ fn dquote_escape_quote() {
|
||||
fn dquote_escape_backtick() {
|
||||
// "\`" should strip backslash, produce literal backtick
|
||||
let result = unescape_str(r#""\`""#);
|
||||
let inner: String = result.chars().filter(|&c| c != markers::DUB_QUOTE).collect();
|
||||
let inner: String = result
|
||||
.chars()
|
||||
.filter(|&c| c != markers::DUB_QUOTE)
|
||||
.collect();
|
||||
assert_eq!(
|
||||
inner, "`",
|
||||
"Escaped backtick should produce literal backtick"
|
||||
@@ -341,7 +356,10 @@ fn dquote_escape_backtick() {
|
||||
fn dquote_escape_nonspecial_preserves_backslash() {
|
||||
// "\a" inside double quotes should preserve the backslash (a is not special)
|
||||
let result = unescape_str(r#""\a""#);
|
||||
let inner: String = result.chars().filter(|&c| c != markers::DUB_QUOTE).collect();
|
||||
let inner: String = result
|
||||
.chars()
|
||||
.filter(|&c| c != markers::DUB_QUOTE)
|
||||
.collect();
|
||||
assert_eq!(
|
||||
inner, "\\a",
|
||||
"Backslash before non-special char should be preserved"
|
||||
@@ -362,10 +380,16 @@ fn dquote_unescaped_dollar_expands() {
|
||||
fn dquote_mixed_escapes() {
|
||||
// "hello \$world \\end" should have literal $, single backslash
|
||||
let result = unescape_str(r#""hello \$world \\end""#);
|
||||
assert!(!result.contains(markers::VAR_SUB), "Escaped $ should not expand");
|
||||
assert!(
|
||||
!result.contains(markers::VAR_SUB),
|
||||
"Escaped $ should not expand"
|
||||
);
|
||||
assert!(result.contains('$'), "Literal $ should be in output");
|
||||
// Should have exactly one backslash (from \\)
|
||||
let inner: String = result.chars().filter(|&c| c != markers::DUB_QUOTE).collect();
|
||||
let inner: String = result
|
||||
.chars()
|
||||
.filter(|&c| c != markers::DUB_QUOTE)
|
||||
.collect();
|
||||
let backslash_count = inner.chars().filter(|&c| c == '\\').count();
|
||||
assert_eq!(backslash_count, 1, "\\\\ should produce one backslash");
|
||||
}
|
||||
|
||||
@@ -4,8 +4,9 @@ use super::*;
|
||||
use crate::expand::{expand_aliases, unescape_str};
|
||||
use crate::libsh::error::{Note, ShErr, ShErrKind};
|
||||
use crate::parse::{
|
||||
NdRule, Node, ParseStream,
|
||||
lex::{LexFlags, LexStream, Tk, TkRule},
|
||||
node_operation, NdRule, Node, ParseStream,
|
||||
node_operation,
|
||||
};
|
||||
use crate::state::{write_logic, write_vars};
|
||||
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
use std::collections::VecDeque;
|
||||
|
||||
use crate::{
|
||||
expand::expand_prompt, libsh::{
|
||||
expand::expand_prompt,
|
||||
libsh::{
|
||||
error::ShErr,
|
||||
term::{Style, Styled},
|
||||
}, prompt::readline::{
|
||||
Prompt, ShedVi, history::History, keys::{KeyCode, KeyEvent, ModKeys}, linebuf::LineBuf, term::{KeyReader, LineWriter, raw_mode}, vimode::{ViInsert, ViMode, ViNormal}
|
||||
}
|
||||
},
|
||||
prompt::readline::{
|
||||
Prompt, ShedVi,
|
||||
history::History,
|
||||
keys::{KeyCode, KeyEvent, ModKeys},
|
||||
linebuf::LineBuf,
|
||||
term::{KeyReader, LineWriter, raw_mode},
|
||||
vimode::{ViInsert, ViMode, ViNormal},
|
||||
},
|
||||
};
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
@@ -251,9 +258,13 @@ fn linebuf_ascii_content() {
|
||||
|
||||
#[test]
|
||||
fn expand_default_prompt() {
|
||||
let prompt = expand_prompt("\\e[0m\\n\\e[1;0m\\u\\e[1;36m@\\e[1;31m\\h\\n\\e[1;36m\\W\\e[1;32m/\\n\\e[1;32m\\$\\e[0m ".into()).unwrap();
|
||||
let prompt = expand_prompt(
|
||||
"\\e[0m\\n\\e[1;0m\\u\\e[1;36m@\\e[1;31m\\h\\n\\e[1;36m\\W\\e[1;32m/\\n\\e[1;32m\\$\\e[0m "
|
||||
.into(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
insta::assert_debug_snapshot!(prompt)
|
||||
insta::assert_debug_snapshot!(prompt)
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::parse::{
|
||||
lex::{LexFlags, LexStream},
|
||||
NdRule, Node, ParseStream, Redir, RedirType,
|
||||
lex::{LexFlags, LexStream},
|
||||
};
|
||||
use crate::procio::{IoFrame, IoMode, IoStack};
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ fn scopestack_new() {
|
||||
|
||||
// Should start with one global scope
|
||||
assert!(stack.var_exists("PATH") || !stack.var_exists("PATH")); // Just check
|
||||
// it doesn't
|
||||
// panic
|
||||
// it doesn't
|
||||
// panic
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user