文盤Rust -- 領域交互模式如何實現

来源:https://www.cnblogs.com/Jcloud/archive/2023/02/13/17117275.html
-Advertisement-
Play Games

書接上文,上回說到如何通過interactcli-rs四步實現一個命令行程式。但是 shell 交互模式在有些場景下用戶體驗並不是很好。比如我們要連接某個服務,比如 mysql 或者 redis 這樣的服務。如果每次交互都需要輸入地址、埠、用戶名等信息,交互起來太麻煩。通常的做法是一次性輸入和連接... ...


作者:京東科技 賈世聞

文盤Rust -- 領域交互模式如何實現

書接上文,上回說到如何通過interactcli-rs四步實現一個命令行程式。但是shell交互模式在有些場景下用戶體驗並不是很好。比如我們要連接某個服務,比如mysql或者redis這樣的服務。如果每次交互都需要輸入地址、埠、用戶名等信息,交互起來太麻煩。通常的做法是一次性輸入和連接相關的信息或者由統一配置文件進行管理,然後進入領域交互模式,所有的命令和反饋都和該領域相關。interactcli-rs 通過 -i 參數實現領域交互模式。這回我們探索一下這一模式是如何實現的。

基本原理

interactcli-rs 實現領域交互模式主要是迴圈解析輸入的每一行,通過rustyline 解析輸入的每一行命令,並交由命令解析函數處理響應邏輯

當我們調用 ‘-i’ 參數的時候 實際上是執行了 interact::run() 函數(interact -> cli -> run())。

pub fn run() {
    let config = Config::builder()
        .history_ignore_space(true)
        .completion_type(CompletionType::List)
        .output_stream(OutputStreamType::Stdout)
        .build();

    let h = MyHelper {
        completer: get_command_completer(),
        highlighter: MatchingBracketHighlighter::new(),
        hinter: HistoryHinter {},
        colored_prompt: "".to_owned(),
        validator: MatchingBracketValidator::new(),
    };

    let mut rl = Editor::with_config(config);
    rl.set_helper(Some(h));

    if rl.load_history("/tmp/history").is_err() {
        println!("No previous history.");
    }

    loop {
        let p = format!("{}> ", "interact-rs");
        rl.helper_mut().expect("No helper").colored_prompt = format!("\x1b[1;32m{}\x1b[0m", p);
        let readline = rl.readline(&p);
        match readline {
            Ok(line) => {
                if line.trim_start().is_empty() {
                    continue;
                }

                rl.add_history_entry(line.as_str());
                match split(line.as_str()).as_mut() {
                    Ok(arg) => {
                        if arg[0] == "exit" {
                            println!("bye!");
                            break;
                        }
                        arg.insert(0, "clisample".to_string());
                        run_from(arg.to_vec())
                    }
                    Err(err) => {
                        println!("{}", err)
                    }
                }
            }
            Err(ReadlineError::Interrupted) => {
                println!("CTRL-C");
                break;
            }
            Err(ReadlineError::Eof) => {
                println!("CTRL-D");
                break;
            }
            Err(err) => {
                println!("Error: {:?}", err);
                break;
            }
        }
    }
    rl.append_history("/tmp/history")
        .map_err(|err| error!("{}", err))
        .ok();
}

解析主邏輯

交互邏輯主要集中在 ‘loop’ 迴圈中,每次迴圈處理一次輸入請求。

處理的邏輯如下

  • 定義提示符,類似 'mysql> ',提示用戶正在使用的程式
 let p = format!("{}> ", "interact-rs");
 rl.helper_mut().expect("No helper").colored_prompt = format!("\x1b[1;32m{}\x1b[0m", p);
  • 讀取輸入行進行解析

    • 將輸入的命令行加入到歷史文件,執行過的命令可以通過上下鍵回放來增強用戶體驗。
    rl.add_history_entry(line.as_str());
    
    • 將輸入的行解析為 arg 字元串,交由 cmd::run_from 函數進行命令解析和執行
    match split(line.as_str()).as_mut() {
                      Ok(arg) => {
                          if arg[0] == "exit" {
                              println!("bye!");
                              break;
                          }
                          arg.insert(0, "clisample".to_string());
                          run_from(arg.to_vec())
                      }
                      Err(err) => {
                          println!("{}", err)
                      }
                  }
    
    • 解析中斷,當用戶執行 ctrl-c 或 ctrl-d 時,退出程式。
       Err(ReadlineError::Interrupted) => {
                  println!("CTRL-C");
                  break;
              }
              Err(ReadlineError::Eof) => {
                  println!("CTRL-D");
                  break;
              }
              Err(err) => {
                  println!("Error: {:?}", err);
                  break;
              }
    

run 函數中其他代碼的作用

  • 配置rustyline
    在 run 函數最開頭 定義了一個config

    let config = Config::builder()
      .history_ignore_space(true)
      .completion_type(CompletionType::List)
      .output_stream(OutputStreamType::Stdout)
      .build();
    

    這個config 其實是rustyline的配置項,包括輸出方式歷史記錄約束,輸出方式等等。

    MyHelper 用於配置命令的 autocomplete

    let h = MyHelper {
      completer: get_command_completer(),
      highlighter: MatchingBracketHighlighter::new(),
      hinter: HistoryHinter {},
      colored_prompt: "".to_owned(),
      validator: MatchingBracketValidator::new(),
    }; 
    

    這裡賣個關子,下期詳細講講 autocomplete 的實現。

  • 配置歷史文件
    run 函數最後,我們為程式配置了歷史文件,應用於存放執行過的歷史命令。這樣即便程式退出,在此打開程式的時候還是可以利用以前的執行歷史。

    rl.append_history("/tmp/history")
          .map_err(|err| error!("{}", err))
          .ok();
    

關於如何構建命令行的領域交互模式就說到這兒,下期詳細介紹一下 autocomplete 如何實現。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 任務平臺是科技內各業務方開展互動玩法的中心化平臺,支撐科技內拉新、促活、交易等業務場景,包含基礎任務、基於任務的通用活動玩法和業務投放能力。提供了任務玩法的創建、投放、曝光、完成等全生命周期的精細化管理,打造了基於任務的裂變、時間軸等通用活動玩法的規則化運營,致力於提升在多場景、多玩法、多頻次的業務... ...
  • 電商網站Web自動化測試實戰( 編寫京東搜索腳本) 1,打開京東頁 京東首頁地址:https://www.jd.com/,故進入京東首頁如下: 2,打開瀏覽器開發者模式 定位元素前需先打開瀏覽器開發者模式,查看頁面源碼 例-打開chrome開發者模式: windows:快捷鍵F12 Mac ios ...
  • 《Terraform 101 從入門到實踐》這本小冊在南瓜慢說官方網站和GitHub兩個地方同步更新,書中的示例代碼也是放在GitHub上,方便大家參考查看。 簡介 Azure是微軟的公有雲,它提供了一些免費的資源,具體可以查看: https://azure.microsoft.com/en-us/ ...
  • 譯者:kefate 原文:https://github.com/google/guice/wiki/Overview 大家好,我是kefate。今天開始我將會把Google Guice的官方文檔陸續翻譯一遍,水平有限,若有翻譯不妥之處,還望各位不吝指出。OK,話不多說,下麵開始今天的正文~ Guic ...
  • ioc,Inversion of Control(控制反轉),是Spring中的一種設計思想而非技術。 我們可以從4個方面理解ioc: ①誰控制誰? ——Ioc容器控制對象。 ②控制了什麼? ——Ioc容器控制了獲取對象及其外部資源。 ③為什麼是反轉? ——傳統的javaSE技術是手動new對象的, ...
  • 這篇文章主要描述分散式系統中的單體調度機制,它是指一個集群中只有一個節點運行調度進程,並介紹Google Borg的單體調度設計思路。 ...
  • SpringMVC底層機制簡單實現-04 https://github.com/liyuelian/springmvc-demo.git 8.任務7-完成簡單視圖解析 功能說明:通過目標方法返回的 String,轉發或重定向到指定頁面 8.1分析 原生的 SpringMVC 使用視圖解析器來對 Ha ...
  • 一、說明 之前項目中一直使用ConcurrentLinkedQueue做為緩衝隊列(主要是單個項目內,單條改批量的場景,多個項目間使用的是rocketmq),雖然用著方便但是是純記憶體的, 如果項目發生異常崩潰記憶體隊列中的數據就會全部丟失(只能從日誌中恢復)。所以一直想找一個簡單高效支持持久化的嵌入式 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...