diff options
| author | salmonik <raisersoft@proton.me> | 2026-07-08 14:39:48 +0200 |
|---|---|---|
| committer | salmonik <raisersoft@proton.me> | 2026-07-08 14:39:48 +0200 |
| commit | e86699c68c8bbc9685bf14466add52b09835f91a (patch) | |
| tree | 8531484c41ed1daf33ac3ab660d112532fe45d8d /src | |
| parent | remember links during audio file completion (diff) | |
| download | senator-sperma-e86699c68c8bbc9685bf14466add52b09835f91a.tar.gz senator-sperma-e86699c68c8bbc9685bf14466add52b09835f91a.zip | |
truncate search results
Signed-off-by: salmonik <raisersoft@proton.me>
Diffstat (limited to 'src')
| -rw-r--r-- | src/commands/autocomplete.rs | 31 |
1 files changed, 17 insertions, 14 deletions
diff --git a/src/commands/autocomplete.rs b/src/commands/autocomplete.rs index 422ab2d..97a18ec 100644 --- a/src/commands/autocomplete.rs +++ b/src/commands/autocomplete.rs | |||
| @@ -8,19 +8,22 @@ type Context<'a> = poise::Context<'a, Data, Error>; | |||
| 8 | 8 | ||
| 9 | const MAX_CHOICE_LEN: usize = 99; | 9 | const MAX_CHOICE_LEN: usize = 99; |
| 10 | 10 | ||
| 11 | fn truncate_choice(s: &str) -> String { | ||
| 12 | if s.chars().count() <= MAX_CHOICE_LEN { | ||
| 13 | return s.to_string(); | ||
| 14 | } | ||
| 15 | let mut t: String = s.chars().take(MAX_CHOICE_LEN - 1).collect(); | ||
| 16 | t.push('\u{2026}'); | ||
| 17 | t | ||
| 18 | } | ||
| 19 | |||
| 11 | fn filename_label(raw_path: &str) -> Option<String> { | 20 | fn filename_label(raw_path: &str) -> Option<String> { |
| 12 | let raw_name = raw_path.rsplit('/').next()?; | 21 | let raw_name = raw_path.rsplit('/').next()?; |
| 13 | if raw_name.is_empty() { | 22 | if raw_name.is_empty() { |
| 14 | return None; | 23 | return None; |
| 15 | } | 24 | } |
| 16 | let decoded = html_decode(&percent_decode(raw_name)); | 25 | let decoded = html_decode(&percent_decode(raw_name)); |
| 17 | if decoded.len() > MAX_CHOICE_LEN { | 26 | Some(truncate_choice(&decoded)) |
| 18 | let mut s: String = decoded.chars().take(MAX_CHOICE_LEN - 1).collect(); | ||
| 19 | s.push('\u{2026}'); | ||
| 20 | Some(s) | ||
| 21 | } else { | ||
| 22 | Some(decoded) | ||
| 23 | } | ||
| 24 | } | 27 | } |
| 25 | 28 | ||
| 26 | pub async fn audio_file<'a>( | 29 | pub async fn audio_file<'a>( |
| @@ -49,13 +52,13 @@ pub async fn audio_file<'a>( | |||
| 49 | let Some(label) = filename_label(&rp) else { | 52 | let Some(label) = filename_label(&rp) else { |
| 50 | continue; | 53 | continue; |
| 51 | }; | 54 | }; |
| 52 | // Stash under the choice VALUE (`rp`), not the display label: | 55 | |
| 53 | // the command receives `rp` as its argument and looks the hit | 56 | let value = truncate_choice(&rp); |
| 54 | // up by that same key, so the cached link is reused instead of | 57 | ctx.data() |
| 55 | // triggering a fresh copyparty search. | 58 | .ac_stash(ctx.author().id, value.clone(), hit) |
| 56 | ctx.data().ac_stash(ctx.author().id, rp.clone(), hit).await; | 59 | .await; |
| 57 | eprintln!("[DEBUG] -> cached as {rp:?}"); | 60 | eprintln!("[DEBUG] -> cached as {value:?}"); |
| 58 | choices.push(serenity::AutocompleteChoice::new(label.clone(), rp)); | 61 | choices.push(serenity::AutocompleteChoice::new(label, value)); |
| 59 | if choices.len() >= 25 { | 62 | if choices.len() >= 25 { |
| 60 | break; | 63 | break; |
| 61 | } | 64 | } |
