taler-rust

GNU Taler code in Rust. Largely core banking integrations.
Log | Files | Refs | Submodules | README | LICENSE

commit f6ce099817e0db979a69eff1f2ac95995dff1c90
parent f0f1480b60a9ae07f7b0f21a4c82106d7610e1ce
Author: Antoine A <>
Date:   Tue, 23 Jun 2026 10:27:37 +0200

test: simplify test repl

Diffstat:
Madapters/taler-magnet-bank/src/db.rs | 19+++++++++----------
Mcommon/taler-test-utils/src/repl.rs | 113+++++++++++++++++++++++++++++++++++++++++--------------------------------------
2 files changed, 67 insertions(+), 65 deletions(-)

diff --git a/adapters/taler-magnet-bank/src/db.rs b/adapters/taler-magnet-bank/src/db.rs @@ -324,7 +324,7 @@ pub async fn register_tx_out( .bind(tx.creditor.iban()) .bind(&tx.creditor.name) .bind_date(&tx.value_date); - let query = match kind { + match kind { TxOutKind::Simple => query .bind(None::<&[u8]>) .bind(None::<&str>) @@ -340,16 +340,15 @@ pub async fn register_tx_out( .bind(subject.exchange_base_url.as_str()) .bind(&subject.metadata) .bind(None::<i64>), - }; - query - .bind_timestamp(now) - .try_map(|r: PgRow| { - Ok(AddOutgoingResult { - result: r.try_get(0)?, - row_id: r.try_get_u64(1)?, - }) + } + .bind_timestamp(now) + .try_map(|r: PgRow| { + Ok(AddOutgoingResult { + result: r.try_get(0)?, + row_id: r.try_get_u64(1)?, }) - .fetch_one(&mut *db) + }) + .fetch_one(&mut *db) }) } diff --git a/common/taler-test-utils/src/repl.rs b/common/taler-test-utils/src/repl.rs @@ -14,7 +14,7 @@ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -use std::borrow::Cow; +use std::{borrow::Cow, marker::PhantomData}; use nu_ansi_term::Color; use reedline::{ @@ -25,59 +25,62 @@ use reedline::{ use crate::cli::clap_parse; -pub async fn test_repl<T: clap::Parser>( - history: &str, - prompt: String, - prepare: impl AsyncFn(), - run: impl AsyncFn(T) -> bool, -) { - let history = Box::new( - FileBackedHistory::with_file(1000, history.into()) - .expect("Error configuring history with file"), - ); - let completion_menu = Box::new( - ColumnarMenu::default() - .with_name("completion_menu") - .with_columns(4) - .with_column_width(None) - .with_column_padding(2), - ); - - let mut insert = default_vi_insert_keybindings(); - insert.add_binding( - KeyModifiers::NONE, - KeyCode::Tab, - ReedlineEvent::UntilFound(vec![ - ReedlineEvent::Menu("completion_menu".to_string()), - ReedlineEvent::MenuNext, - ]), - ); - let mut relp = Reedline::create() - .with_history(history) - .with_completer(Box::new(ClapCompleter(T::command()))) - .with_menu(ReedlineMenu::EngineCompleter(completion_menu)) - .with_quick_completions(true) - .with_partial_completions(true) - .with_hinter(Box::new(DefaultHinter::default().with_style( - nu_ansi_term::Style::new().italic().fg(Color::LightGray), - ))) - .with_edit_mode(Box::new(Vi::new(insert, default_vi_normal_keybindings()))); - - let prompt = ReplPrompt(prompt); - loop { - prepare().await; - let Signal::Success(buf) = relp.read_line(&prompt).unwrap() else { - break; - }; - match clap_parse(&buf) { - Ok(cmd) => { - if run(cmd).await { - break; +pub struct Repl<T: clap::Parser> { + relp: Reedline, + cmd: PhantomData<T>, +} + +impl<T: clap::Parser> Repl<T> { + pub fn new(history: &str) -> Self { + let history = Box::new( + FileBackedHistory::with_file(1000, history.into()) + .expect("Error configuring history with file"), + ); + let completion_menu = Box::new( + ColumnarMenu::default() + .with_name("completion_menu") + .with_columns(4) + .with_column_width(None) + .with_column_padding(2), + ); + + let mut insert = default_vi_insert_keybindings(); + insert.add_binding( + KeyModifiers::NONE, + KeyCode::Tab, + ReedlineEvent::UntilFound(vec![ + ReedlineEvent::Menu("completion_menu".to_string()), + ReedlineEvent::MenuNext, + ]), + ); + let repl = Reedline::create() + .with_history(history) + .with_completer(Box::new(ClapCompleter(T::command()))) + .with_menu(ReedlineMenu::EngineCompleter(completion_menu)) + .with_quick_completions(true) + .with_partial_completions(true) + .with_hinter(Box::new(DefaultHinter::default().with_style( + nu_ansi_term::Style::new().italic().fg(Color::LightGray), + ))) + .with_edit_mode(Box::new(Vi::new(insert, default_vi_normal_keybindings()))); + + Self { + relp: repl, + cmd: PhantomData, + } + } + + pub fn read_line(&mut self, prompt: &str) -> Option<T> { + loop { + let Signal::Success(buf) = self.relp.read_line(&ReplPrompt(prompt)).unwrap() else { + return None; + }; + match clap_parse(&buf) { + Ok(cmd) => return Some(cmd), + Err(e) => { + println!("{e}"); } } - Err(e) => { - println!("{e}"); - } } } } @@ -184,11 +187,11 @@ impl reedline::Completer for ClapCompleter { } } -struct ReplPrompt(String); +struct ReplPrompt<'a>(&'a str); -impl reedline::Prompt for ReplPrompt { +impl<'a> reedline::Prompt for ReplPrompt<'a> { fn render_prompt_left(&self) -> Cow<'_, str> { - Cow::Borrowed(&self.0) + Cow::Borrowed(self.0) } fn render_prompt_right(&self) -> Cow<'_, str> {