properly display quoted queries

This commit is contained in:
kageru 2023-01-31 11:47:59 +01:00
parent 3385401e73
commit 944b9412f4
2 changed files with 16 additions and 10 deletions

@ -18,7 +18,7 @@ static CARDS: LazyLock<Vec<Card>> = LazyLock::new(|| {
.data .data
}); });
static CARDS_BY_ID: LazyLock<HashMap<usize, Card>> = static CARDS_BY_ID: LazyLock<HashMap<usize, Card>> =
LazyLock::new(|| CARDS.iter().map(|c| (c.id, Card { text: c.text.replace("\r", "").replace('\n', "<br/>"), ..c.clone() })).collect()); LazyLock::new(|| CARDS.iter().map(|c| (c.id, Card { text: c.text.replace('\r', "").replace('\n', "<br/>"), ..c.clone() })).collect());
static SEARCH_CARDS: LazyLock<Vec<SearchCard>> = LazyLock::new(|| CARDS.iter().map(SearchCard::from).collect()); static SEARCH_CARDS: LazyLock<Vec<SearchCard>> = LazyLock::new(|| CARDS.iter().map(SearchCard::from).collect());
#[actix_web::main] #[actix_web::main]
@ -109,14 +109,14 @@ fn render_searchbox(res: &mut String, query: &Option<String>) -> std::fmt::Resul
<input type="text" name="q" id="searchbox" placeholder="Enter query (e.g. l:5 c:synchro atk>2000)" value="{}"><input type="submit" id="submit" value="🔍"> <input type="text" name="q" id="searchbox" placeholder="Enter query (e.g. l:5 c:synchro atk>2000)" value="{}"><input type="submit" id="submit" value="🔍">
</form>"#, </form>"#,
match &query { match &query {
Some(q) => q, Some(q) => q.replace('"', "&quot;"),
None => "", None => String::new(),
} }
) )
} }
fn render_results(res: &mut String, query: &str) -> Result<(), Box<dyn std::error::Error>> { fn render_results(res: &mut String, query: &str) -> Result<(), Box<dyn std::error::Error>> {
let query = match parser::parse_filters(query) { let (raw_filters, query) = match parser::parse_filters(query) {
Ok(q) => q, Ok(q) => q,
Err(e) => { Err(e) => {
write!(res, "Could not parse query: {e:?}")?; write!(res, "Could not parse query: {e:?}")?;
@ -126,7 +126,7 @@ fn render_results(res: &mut String, query: &str) -> Result<(), Box<dyn std::erro
let now = Instant::now(); let now = Instant::now();
let matches: Vec<&Card> = SEARCH_CARDS let matches: Vec<&Card> = SEARCH_CARDS
.iter() .iter()
.filter(|card| query.iter().all(|(_, q)| q(card))) .filter(|card| query.iter().all(|q| q(card)))
.map(|c| CARDS_BY_ID.get(&c.id).unwrap()) .map(|c| CARDS_BY_ID.get(&c.id).unwrap())
.take(RESULT_LIMIT) .take(RESULT_LIMIT)
.collect(); .collect();
@ -134,7 +134,7 @@ fn render_results(res: &mut String, query: &str) -> Result<(), Box<dyn std::erro
res, res,
"<span class=\"meta\">Showing {} results where {} (took {:?})</span>", "<span class=\"meta\">Showing {} results where {} (took {:?})</span>",
matches.len(), matches.len(),
query.iter().map(|(f, _)| f.to_string()).join(" and "), raw_filters.iter().map(|f| f.to_string()).join(" and "),
now.elapsed() now.elapsed()
)?; )?;
if matches.is_empty() { if matches.is_empty() {

@ -14,11 +14,11 @@ use nom::{
IResult, IResult,
}; };
pub fn parse_filters(input: &str) -> Result<Vec<(RawCardFilter, CardFilter)>, String> { pub fn parse_filters(input: &str) -> Result<(Vec<RawCardFilter>, Vec<CardFilter>), String> {
parse_raw_filters(input).map_err(|e| format!("Error while parsing filters “{input}”: {e:?}")).and_then(|(rest, mut v)| { parse_raw_filters(input).map_err(|e| format!("Error while parsing filters “{input}”: {e:?}")).and_then(|(rest, mut v)| {
if rest.is_empty() { if rest.is_empty() {
v.sort_unstable_by_key(|RawCardFilter(f, _, _)| *f as u8); v.sort_unstable_by_key(|RawCardFilter(f, _, _)| *f as u8);
v.into_iter().map(|r| build_filter(r.clone()).map(|f| (r, f))).collect() Ok((v.clone(), v.into_iter().map(|r| build_filter(r)).collect::<Result<Vec<_>, _>>()?))
} else { } else {
Err(format!("Input was not fully parsed. Left over: “{rest}")) Err(format!("Input was not fully parsed. Left over: “{rest}"))
} }
@ -180,8 +180,14 @@ pub enum Value {
impl Display for Value { impl Display for Value {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self { match &self {
Self::String(s) => f.write_str(s), Self::String(s) => {
Self::Numerical(n) => write!(f, "{}", n), if s.contains(' ') {
write!(f, "\"{s}\"")
} else {
f.write_str(s)
}
}
Self::Numerical(n) => write!(f, "{n}"),
} }
} }
} }