From f03cfd829a4b0b46a894867cd36ee453aeec85bb Mon Sep 17 00:00:00 2001 From: neko0xff Date: Sun, 19 May 2024 14:05:28 +0800 Subject: [PATCH 01/12] 20240519 update1 --- README.md | 6 ++- book.toml | 2 +- src/README.md | 29 +++----------- src/SUMMARY.md | 34 ++++++++-------- src/in-depth/README.md | 5 +-- src/in-depth/config-files.md | 26 ++++++------ src/in-depth/docs.md | 10 +++-- src/in-depth/exit-code.md | 10 ++++- src/in-depth/signals.md | 2 +- src/resources/README.md | 15 +++---- src/tutorial/README.md | 77 +++++++++++++----------------------- src/tutorial/cli-args.md | 75 ++++++++++++++--------------------- src/tutorial/errors.md | 4 +- src/tutorial/output.md | 21 +++++----- src/tutorial/setup.md | 30 ++++++-------- src/tutorial/testing.md | 44 ++++++++------------- 16 files changed, 168 insertions(+), 222 deletions(-) diff --git a/README.md b/README.md index b2d50c7..943703e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Command Line Applications in Rust +# Rust 中的命令列應用程式 This repo contains the CLAiR, the [Command Line Applications in Rust][clair] book. It is written and updated by the [Rust CLI working group][wg]. @@ -31,10 +31,12 @@ $ mdbook test ## Multi-language support Unofficial translation: -- 中文(zh_CN):[Rust 中的命令行应用][rust-cli-zh_CN] (2021-09-13) +- 簡體中文(zh_CN):[Rust 中的命令行应用][rust-cli-zh_CN] (2021-09-13) - 한글(ko_KR):[Rust 커맨드라인 애플리케이션][rust-cli-ko_KR] (2023-05-31) +- 繁體中文(zh_TW):[Rust 中的命令列應用程式][rust-cli-zh_TW] (2024-05-19) [clair]: https://rust-cli.github.io/book/ [wg]: https://github.com/rust-cli/meta [rust-cli-zh_CN]: https://suibianxiedianer.github.io/rust-cli-book-zh_CN/ [rust-cli-ko_KR]: https://parksb.github.io/rust-cli-book-ko-kr/ +[rust-cli-zh_TW]: diff --git a/book.toml b/book.toml index c7b4b3e..a465177 100644 --- a/book.toml +++ b/book.toml @@ -1,6 +1,6 @@ [book] # This book is called -title = "Command Line Applications in Rust" +title = "Rust 中的命令列應用程式" # ...but friends call it "Clair" authors = ["The Rust CLI Working Group"] multilingual = false diff --git a/src/README.md b/src/README.md index 9a3b5b2..b264ebf 100644 --- a/src/README.md +++ b/src/README.md @@ -1,30 +1,11 @@ -# Command line apps in Rust +# Rust 中的命令列應用程式 -Rust is a statically compiled, fast language with great tooling and a rapidly growing ecosystem. -That makes it a great fit for writing command line applications: -They should be small, portable, and quick to run. -Command line applications are also a great way to get started with learning Rust; -or to introduce Rust to your team! +Rust 是一種靜態編譯的、運行速度快的語言,它擁有強大的工具,其生態也在快速發展。 這使得它非常適合編寫命令列應用:小巧、便攜且運行速度快。 而命令列應用也是開始進行 Rust 學習,或向你的團隊介紹 Rust 的一種很好的方式。 -Writing a program with a simple command line interface (CLI) -is a great exercise for a beginner -who is new to the language and wants to get a feel for it. -There are many aspects to this topic, though, -that often only reveal themselves later on. +編寫一個簡單的命令列介面程式(CLI)對於剛接觸 Rust 且希望對其有所了解的初學者來說,是一個很好的練習。不過,這裡面也包含了許多方面,後面我們會介紹到它們。 -This book is structured like this: -We start with a quick tutorial, -after which you'll end up with a working CLI tool. -You'll be exposed to a few of the core concepts of Rust -as well as the main aspects of CLI applications. -What follows are chapters that go into more detail -on some of these aspects. +本書的大綱如下: 首先我們從一個快速教學開始,完成後你將會得到一個可用的 CLI 工具。 透過此教程, 你將接觸到 RUST 的一些核心概念及 CLI 應用的主要包括了哪些部分功能。 而下面的章節則是介紹這些面向的實作細節。 -One last thing before we dive right into CLI applications: -If you find an error in this book -or want to help us write more content for it, -you can find its source [in the CLI book repository][book-src]. -We'd love to hear your feedback! -Thank you! +最後,也是非常重要的一件事:如果在本書發現了錯誤,或想貢獻、豐富本書的內容, 項目源碼在這裡 [in the CLI WG repository][book-src] ,期待你的反饋! [book-src]: https://github.com/rust-cli/book diff --git a/src/SUMMARY.md b/src/SUMMARY.md index f861e6c..48ad67d 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -1,20 +1,20 @@ # Summary -[Getting started](./README.md) +[開始](./README.md) -- [A command line app in 15 minutes](./tutorial/README.md) - - [Project setup](./tutorial/setup.md) - - [Parsing command line arguments](./tutorial/cli-args.md) - - [First implementation](./tutorial/impl-draft.md) - - [Nicer error reporting](./tutorial/errors.md) - - [Output for humans and machines](./tutorial/output.md) - - [Testing](./tutorial/testing.md) - - [Packaging and distributing a Rust tool](./tutorial/packaging.md) -- [In-depth topics](./in-depth/README.md) - - [Signal handling](./in-depth/signals.md) - - [Using config files](./in-depth/config-files.md) - - [Exit codes](./in-depth/exit-code.md) - - [Communicating with humans](./in-depth/human-communication.md) - - [Communicating with machines](./in-depth/machine-communication.md) - - [Rendering documentation for your CLI apps](./in-depth/docs.md) -- [Resources](./resources/README.md) +- [在15分鐘內建立一個命令列應用程式](./tutorial/README.md) + - [專案初始化設置](./tutorial/setup.md) + - [解析命令列參數](./tutorial/cli-args.md) + - [首次運行](./tutorial/impl-draft.md) + - [合適的反饋錯誤](./tutorial/errors.md) + - [輸出](./tutorial/output.md) + - [測試](./tutorial/testing.md) + - [打包且發布一個Rust工具](./tutorial/packaging.md)z +- [深入探究主題](./in-depth/README.md) + - [訊號處理](./in-depth/signals.md) + - [使用配置檔](./in-depth/config-files.md) + - [退出狀態碼](./in-depth/exit-code.md) + - [和人互動](./in-depth/human-communication.md) + - [和機器互動](./in-depth/machine-communication.md) + - [為你的 CLI 程式產生文檔](./in-depth/docs.md) +- [相關資源](./resources/README.md) diff --git a/src/in-depth/README.md b/src/in-depth/README.md index 13b6edd..22e4cff 100644 --- a/src/in-depth/README.md +++ b/src/in-depth/README.md @@ -1,4 +1,3 @@ -# In-depth topics +# 深入探究主題 -A small collection of chapters covering some more details -that you might care about when writing your command line application. +該章節會涵蓋更多較為進階的小細節,但您在編寫命令列應用程式時可能會在乎這一點。 diff --git a/src/in-depth/config-files.md b/src/in-depth/config-files.md index 4588b11..d3dc0cb 100644 --- a/src/in-depth/config-files.md +++ b/src/in-depth/config-files.md @@ -1,12 +1,16 @@ -# Using config files +# 使用配置檔 Dealing with configurations can be annoying especially if you support multiple operating systems which all have their own places for short- and long-term files. -There are multiple solutions to this, -some being more low-level than others. +處理配置可能很煩人 +特別是如果您支援多個作業系統 +都有自己的位置 +適用於短期和長期文件。 + +對此有許多解決方案,有些比其他的層次更低。 The easiest crate to use for this is [`confy`]. It asks you for the name of your application @@ -29,22 +33,22 @@ fn main() -> Result<(), io::Error> { } ``` -This is incredibly easy to use -for which you of course surrender configurability. -But if a simple config is all you want, -this crate might be for you! +這非常容易使用 +為此,您當然要放棄可設定性。 +但如果你想要一個簡單的配置, +這個crate可能適合你! [`confy`]: https://docs.rs/confy/0.3.1/confy/ -## Configuration environments +## 配置環境 diff --git a/src/in-depth/docs.md b/src/in-depth/docs.md index c077514..294c1c0 100644 --- a/src/in-depth/docs.md +++ b/src/in-depth/docs.md @@ -1,13 +1,14 @@ -# Rendering documentation for your CLI apps +# 為你的 CLI 程式產生文檔 -Documentation for CLIs usually consists of -a `--help` section in the command -and a manual (`man`) page. +CLI 的文檔通常包括指令中的 `--help` 部分和一個手冊(`man`)頁面。 Both can be automatically generated when using [`clap`](https://crates.io/crates/clap), via [`clap_mangen`](https://crates.io/crates/clap_mangen) crate. +兩者都可以自動生成 +使用 [`clap`](https://crates.io/crates/clap) 時,透過[`clap_mangen`](https://crates.io/crates/clap_mangen) 箱。 + ```rust,ignore #[derive(Parser)] pub struct Head { @@ -56,3 +57,4 @@ in your project directory. If you open that in `man` you'll be able to admire your free documentation. +如果你在 `man` 中打開它,則你可閱讀 diff --git a/src/in-depth/exit-code.md b/src/in-depth/exit-code.md index ce7ed76..3eee5c1 100644 --- a/src/in-depth/exit-code.md +++ b/src/in-depth/exit-code.md @@ -1,4 +1,4 @@ -# Exit codes +# 退出狀態碼 A program doesn't always succeed. And when an error occurs, @@ -15,6 +15,14 @@ For example, in the ideal case when your program succeeds, it should exit with `0`. +一個計劃並不總是成功。 +並且當出現錯誤時,您應該確保正確發出必要的資訊。 +另外[告訴使用者錯誤]( human-communication.html), +在大多數系統上,當進程退出時,它還發出退出代碼(0 到 255 之間的整數與大多數平台相容)。 +您應該嘗試發出正確的程式碼 +對於你的程式的狀態。 +例如,在您的計劃成功的理想情況下,它應該以“0”退出。 + When an error occurs, it gets a bit more complicated, though. In the wild, many tools exit with `1` when a common failure occurs. diff --git a/src/in-depth/signals.md b/src/in-depth/signals.md index 780b34d..e184af7 100644 --- a/src/in-depth/signals.md +++ b/src/in-depth/signals.md @@ -1,4 +1,4 @@ -# Signal handling +# 訊號處理 Processes like command line applications diff --git a/src/resources/README.md b/src/resources/README.md index 7f8b007..fde3fd2 100644 --- a/src/resources/README.md +++ b/src/resources/README.md @@ -1,9 +1,9 @@ -# Resources +# 相關資源 -Collaboration / help +協作/幫助 - [cli-and-tui Discord Channel](https://discord.com/channels/273534239310479360/943315667430563862) -## Crates referenced in this book +## 本書中引用的參考crates - [anyhow](https://crates.io/crates/anyhow) - provides `anyhow::Error` for easy error handling - [assert_cmd](https://crates.io/crates/assert_cmd) - simplifies integration testing of CLIs @@ -26,10 +26,11 @@ Collaboration / help - [tokio](https://crates.io/crates/tokio) - asynchronous runtime - [wasm-pack](https://crates.io/crates/wasm-pack) - tool for building WebAssembly -## Other crates +## 其它 crates -Due to the constantly-changing landscape of Rust crates, a good place to find -crates is the [lib.rs](https://lib.rs) crate index, including: +由於 Rust crates 的landscape不斷變化,這是一個尋找的好地方。 + +crates 是 [lib.rs](https://lib.rs) crate 索引,包括: - [Command-line interface](https://lib.rs/command-line-interface) - [Configuration](https://lib.rs/config) - [Database interfaces](https://lib.rs/database) @@ -38,6 +39,6 @@ crates is the [lib.rs](https://lib.rs) crate index, including: - [HTTP Client](https://lib.rs/web-programming/http-client) - [Operating systems](https://lib.rs/os) -Other resources: +其他資源: - [Rust Cookbook](https://rust-lang-nursery.github.io/rust-cookbook/) - [rosetta-rs](https://github.com/rosetta-rs) diff --git a/src/tutorial/README.md b/src/tutorial/README.md index f7d2bda..26b6873 100644 --- a/src/tutorial/README.md +++ b/src/tutorial/README.md @@ -1,60 +1,40 @@ -# Learning Rust by Writing a Command Line App in 15 Minutes +# 在15分鐘內建立一個命令列應用程式 -This tutorial will guide you through writing -a CLI (command line interface) application -in [Rust]. -It will take you roughly fifteen minutes -to get to a point where you have a running program -(around chapter 1.3). -After that, we'll continue to tweak our program -until we reach a point where we can ship our little tool. +本教學將指導您建立CLI(命令列介面)應用程式 + +在[Rust]中,只需大約需要十五分鐘,就能得到可以運行的程式(大約第 1.3 節以後)。 + +之後,我們只需持續調整我們的程式,直到它可以被當作一個工具來打包發布。 [Rust]: https://rust-lang.org/ -You’ll learn all the essentials about how to get going, -and where to find more information. -Feel free to skip parts you don't need to know right now -or jump in at any point. +你將學到如何開始所需的所有基本知識,以及如何去尋找更多有用資訊。 +當然,你可隨意跳過目前不需要了解的章節,或之後再翻回查看。 -[community page]: https://www.rust-lang.org/community +你想要寫一個什麼樣的專案呢? - +不如我們先從一個簡單的開始:讓我們寫一個簡單的 `grep`。 -What kind of project do you want to write? -How about we start with something simple: -Let’s write a small `grep` clone. -That is a tool that we can give a string and a path -and it’ll print only the lines that contain the given string. -Let’s call it `grrs` (pronounced “grass”). +我們給這個工具一個字串和一個檔案路徑,它將列印出每個包含所查字串的行。 不如就叫它 `grrs` 吧(發音“grass”)。 -In the end, -we want to be able to run our tool like this: +最後,我們想讓它像這樣運行: ```console $ cat test.txt foo: 10 @@ -68,15 +48,12 @@ $ grrs --help -## Question Mark +## 問題標記 Just like calling `.unwrap()` is a shortcut for the `match` with `panic!` in the error arm, diff --git a/src/tutorial/output.md b/src/tutorial/output.md index 901b85e..f528e28 100644 --- a/src/tutorial/output.md +++ b/src/tutorial/output.md @@ -1,32 +1,35 @@ -# Output +# 輸出 -## Printing "Hello World" +## 在終端機下輸出 "Hello World" ```rust println!("Hello World"); ``` -Well, that was easy. -Great, onto the next topic. +嗯,這很容易。 +太好了,進入下一個主題。 -## Using `println!` +## 使用 `println!` -You can pretty much print all the things you like -with the `println!` macro. +您幾乎可以在終端機下使用 `println!` 巨集輸出所有您想輸出的東西。 + +這個巨集有一些非常驚人的功能,而且還有特殊的語法。 +它希望您編寫一個字串文字作為第一個參數,包含將要填入的佔位符 +再透過後面作為進一步參數的參數值。 This macro has some pretty amazing capabilities, but also a special syntax. It expects you to write a string literal as the first parameter, that contains placeholders that will be filled in by the values of the parameters that follow as further arguments. -For example: +範例: ```rust let x = 42; println!("My lucky number is {}.", x); ``` -will print +將會輸出 ```console My lucky number is 42. diff --git a/src/tutorial/setup.md b/src/tutorial/setup.md index dca729c..515f0ef 100644 --- a/src/tutorial/setup.md +++ b/src/tutorial/setup.md @@ -1,27 +1,21 @@ -# Project setup +# 專案初始化設置 -If you haven’t already, -[install Rust] on your computer -(it should only take a few minutes). -After that, open a terminal and navigate to the directory -you want to put your application code into. +如果你還沒有在你的電腦上[安裝 Rust](應該只需要幾分鐘就能完成)。 -[install Rust]: https://www.rust-lang.org/tools/install +然後,請打開終端機並切換到你的工作目錄,程式原始碼將會放置在這裡。 -Start by running -`cargo new grrs` -in the directory you store your programming projects in. -If you look at the newly created `grrs` directory, -you’ll find a typical setup for a Rust project: +[安裝 Rust]: https://www.rust-lang.org/tools/install -- A `Cargo.toml` file that contains metadata for our project, - incl. a list of dependencies/external libraries we use. -- A `src/main.rs` file that is the entry point for our (main) binary. +請開始在你想建立專案的目錄下執行`cargo new grrs`。 -If you can execute `cargo run` in the `grrs` directory -and get a "Hello World", you’re all set up. +如果你查看新建立的 `grrs` 目錄,你會發現 Rust 專案的預設設定: -## What it might look like +- `Cargo.toml` 裡包含了我們專案所有的中繼資料,包括我們使用依賴/外部函式庫列表。 +- `src/main.rs` 是我們程式的二進制入口檔案(主程式)。 + +如果可以在`grrs`目錄下執行`cargo run`並得到一個“Hello World”,那你就已經準備好了。 + +## 它可能會是什麼樣子 ```console $ cargo new grrs diff --git a/src/tutorial/testing.md b/src/tutorial/testing.md index 646768d..3744799 100644 --- a/src/tutorial/testing.md +++ b/src/tutorial/testing.md @@ -1,39 +1,29 @@ -# Testing - -Over decades of software development, -people have discovered one truth: -Untested software rarely works. -(Many people would go as far as saying: -"Most tested software doesn't work either." -But we are all optimists here, right?) -So, to ensure that your program does what you expect it to do, -it is wise to test it. - -One easy way to do that is -to write a `README` file -that describes what your program should do. -And when you feel ready to make a new release, -go through the `README` and ensure that -the behavior is still as expected. -You can make this a more rigorous exercise -by also writing down how your program should react to erroneous inputs. - -Here's another fancy idea: -Write that `README` before you write the code. +# 測試 + +經過數十年的軟體開發,人們發現了一個真理:未經測試的軟體很少能運作。 +(很多人甚至會說:“大多數經過測試的軟體也無法運行。”但我們都是樂觀主義者,對吧?) + +因此,為了確保您的程式執行您期望的操作,測試它是明智的。 + +一種簡單的方法是編寫 `README` 文件,它描述了你的程式應該做什麼。 +當您準備好發布新版本時,仔細閱讀 `README` 並確保行為仍然如預期。 +你可以讓它成為一個更嚴格的練習也寫下您的程式應如何對錯誤輸入做出反應。 + +這是另一個獨特的想法: +在編寫程式碼之前先寫下 `README`。 -## Automated testing +## 自動化測試 Now, this is all fine and dandy, but doing all of this manually? From 668c7aac0c1267a8a4b47db02b04b6aecdb95e5d Mon Sep 17 00:00:00 2001 From: neko0xff Date: Mon, 20 May 2024 14:52:16 +0800 Subject: [PATCH 02/12] 20240520 update --- src/tutorial/cli-args.md | 105 ++++++++++++++++------------------- src/tutorial/errors.md | 109 +++++++++++++++++-------------------- src/tutorial/impl-draft.md | 46 +++++++--------- 3 files changed, 118 insertions(+), 142 deletions(-) diff --git a/src/tutorial/cli-args.md b/src/tutorial/cli-args.md index 9f72acf..87f63d2 100644 --- a/src/tutorial/cli-args.md +++ b/src/tutorial/cli-args.md @@ -12,7 +12,7 @@ $ grrs foobar test.txt 在命令列中,程式名稱中後面的文字通常被稱為「命令列參數(command-line arguments)」或「命令列標籤(command-line flags)」(尤其是當他們看起來像 `--this`)。 -作業系統通常會將它們識別為字串列表——簡單的說,以空格分隔。 +作業系統通常會將它們識別為字串列表 --- 簡單的說,以空格分隔。 有很多方法可以識別這些參數並解析,使它們變得更易於使用。 @@ -44,7 +44,7 @@ pattern: "some-pattern", path: "some-file" ## CLI 參數的資料類型 -與其將它們視為單純的一堆文本,不如將 CLI 參數看成程式輸入的自訂的資料類型。 +與其將它們視為單純的一堆文字,不如將 CLI 參數看成程式輸入的自訂的資料類型。 注意 `grrs foobar test.txt`: 這裡有兩個參數,首先是 `pttern`(查看的字串), 然後才是 `path`(尋找的檔案路徑)。 @@ -55,63 +55,60 @@ pattern: "some-pattern", path: "some-file" 此外,關於參數的類型:pattern 應該是字串;第二個參數則應是檔案的路徑。 -在Rust 中,根據所處理的資料去建立程式是很常見的, 因此這種看待參數的方法對我們接下來的工作很有幫助。 +在Rust 中,根據所處理的資料而去建立程式是很常見的, 因此這種看待參數的方法對我們接下來的工作很有幫助。 -讓我們以此開始(在 `src/main.rs`,`fn main( ) {` 之前 ): +讓我們在這開始(在檔案 `src/main.rs`,`fn main( ) {` 之前 ): ```rust,ignore {{#include cli-args-struct.rs:1:4}} ``` -This defines a new structure (a [`struct`]) -that has two fields to store data in: `pattern`, and `path`. +這定義了一個新的結構體(a [`struct`]) +它有兩個欄位來儲存資料: `patern` 和 `path` 。 [`struct`]: https://doc.rust-lang.org/1.39.0/book/ch05-00-structs.html -Now, we still need to get the actual arguments our program got into this form. -One option would be to manually parse the list of strings we get from the operating system -and build the structure ourselves. -It would look something like this: +現在,我們仍然需要取得我們的程式進入這種形式的實際參數。 + +有一種做法就是我們可以手動解析從作業系統上取得的參數列表並以此產生一個結構體。 + +就有點像是這樣: ```rust,ignore {{#include cli-args-struct.rs:6:16}} ``` -This works, but it's not very convenient. -How would you deal with the requirement to support -`--pattern="foo"` or `--pattern "foo"`? -How would you implement `--help`? +這種方式能正常運作,但用起來卻不是很方便。 +如何去支援像 `--pattern="foo"` 或 `--pattern "foo"` 這種參數輸入? +又如何去實現 `--help`? -## Parsing CLI arguments with Clap +## 使用 Clap 解析 CLI 參數 -A much nicer way is to use one of the many available libraries. -The most popular library for parsing command-line arguments -is called [`clap`]. -It has all the functionality you'd expect, -including support for sub-commands, [shell completions], and great help messages. +使用現成的函式庫來實現參數的解析,這是更明智的選擇。 +[`clap`] 是目前最受歡迎的解析命令列參數的函式庫。 +它提供了所有你需要的功能, 如子指令、[自動補全][shell completions] 和完善的幫助資訊。 [`clap`]: https://docs.rs/clap/ [shell completions]: https://docs.rs/clap_complete/ -Let's first import `clap` by adding -`clap = { version = "4.0", features = ["derive"] }` to the `[dependencies]` section -of our `Cargo.toml` file. +首先,我們需要在 `Cargo.toml` 檔案的 `[dependencies]` 欄位裡加入上 `clap = { version = "4.0", features = ["derive"] }` 來匯入 `clap`。 + +現在,我們可以在程式碼中加入`use clap::Parser;`, +和在先前建立的 `struct Cli` 的正上方加上 `#[derive(Parser)]`。 -Now, we can write `use clap::Parser;` in our code, -and add `#[derive(Parser)]` right above our `struct Cli`. -Let's also write some documentation comments along the way. +我們也可以在過程中編寫一些文件註解。 -It’ll look like this (in file `src/main.rs`, before `fn main() {`): +讓我們在這開始(在檔案 `src/main.rs`,`fn main( ) {` 之前 ): ```rust,ignore {{#include cli-args-clap.rs:1:10}} @@ -119,53 +116,46 @@ It’ll look like this (in file `src/main.rs`, before `fn main() {`): -Right below the `Cli` struct our template contains its `main` function. -When the program starts, it will call this function: +在本範例中,我們的 `Cli` 結構體下方即是 main 函數。 +當開始執行程式時,就會呼叫這個函數: ```rust,ignore {{#include cli-args-clap.rs:12:16}} ``` -This will try to parse the arguments into our `Cli` struct. +這將嘗試解析參數並儲存到 `Cli` 結構體中。 -But what if that fails? -That's the beauty of this approach: -Clap knows which fields to expect, -and what their expected format is. -It can automatically generate a nice `--help` message, -as well as give some great errors -to suggest you pass `--output` when you wrote `--putput`. +但如果解析失敗會怎樣? +這就是使用此方法的美妙之處:Clap 知道它需要什麼字段, 及所需字段的類型。 +它可以自動產生一個不錯的 `--help` 訊息, 並會依錯誤給予一些建議-輸入的參數應該是 `--output` 而你輸入的是 `--putput`。 -## Wrapping up +## 總結 -Your code should now look like: +你的程式碼現在看起來應該是這樣的: ```rust,ignore {{#include cli-args-clap.rs}} ``` -Running it without any arguments: +在無指定參數運作時: ```console $ cargo run @@ -181,7 +171,7 @@ USAGE: For more information try --help ``` -Running it passing arguments: +如果使用傳遞參數: ```console $ cargo run -- some-pattern some-file @@ -190,5 +180,4 @@ $ cargo run -- some-pattern some-file pattern: "some-pattern", path: "some-file" ``` -The output demonstrates that our program successfully -parsed the arguments into the `Cli` struct. +該輸出表示我們的程式成功將參數解析為 `Cli` 結構。 diff --git a/src/tutorial/errors.md b/src/tutorial/errors.md index b7c6dac..aed36ba 100644 --- a/src/tutorial/errors.md +++ b/src/tutorial/errors.md @@ -1,28 +1,25 @@ # 合適的反饋錯誤 -We all can do nothing but accept the fact that errors will occur. -And in contrast to many other languages, -it's very hard not to notice and deal with this reality -when using Rust: -As it doesn't have exceptions, -all possible error states are often encoded in the return types of functions. - -## Results - -A function like [`read_to_string`] doesn't return a string. -Instead, it returns a [`Result`] -that contains either -a `String` -or an error of some type -(in this case [`std::io::Error`]). +我們都無能為力,只能接受錯誤會發生的事實。 + +與許多其他語言相比,很難不去注意和應對這個現實 +使用 Rust 時: +既然沒有例外,所有可能的錯誤狀態通常都編碼在函數的傳回類型中。 + +## 結果 + +像 [`read_to_string`] 這樣的函數不回傳字串。 +相反的,它會傳回一個 [`Result`],裡面包含一個“字串”或某種其它類型的錯誤 +(在本例中為[`std::io::Error`])。 [`read_to_string`]: https://doc.rust-lang.org/1.39.0/std/fs/fn.read_to_string.html [`Result`]: https://doc.rust-lang.org/1.39.0/std/result/index.html [`std::io::Error`]: https://doc.rust-lang.org/1.39.0/std/io/type.Result.html -How do you know which it is? -Since `Result` is an `enum`, -you can use `match` to check which variant it is: +那麼如何得知是哪一種類型呢? + +因為 `Result` 也是 `enum` 類型, +可以使用 `match` 去檢查裡面是哪一種變體: ```rust,no_run let result = std::fs::read_to_string("test.txt"); @@ -34,20 +31,21 @@ match result { -## Unwrapping +## 展開 -Now, we were able to access the content of the file, -but we can't really do anything with it after the `match` block. -For this, we'll need to somehow deal with the error case. -The challenge is that all arms of a `match` block need to return something of the same type. -But there's a neat trick to get around that: +現在,我們可以存取文件的內容,但在 `match` 程式碼區塊後無法對它做任何事情。 + +因此,我們需要以某種方式處理錯誤的情況。 +因難點在於, `match` 程式碼區塊的所有分支都會回傳一個相同的型別。 + +但有一個巧妙的技巧來解決這個問題: ```rust,no_run let result = std::fs::read_to_string("test.txt"); @@ -58,25 +56,23 @@ let content = match result { println!("file content: {}", content); ``` -We can use the String in `content` after the match block. -If `result` were an error, the String wouldn't exist. -But since the program would exit before it ever reached a point where we use `content`, -it's fine. +我們可以在 `match` 程式碼區塊後使用 `content`。 +如果 `result` 是個錯誤, 字串就不存在。 +但好家在,程式會在我們使用 `content` 之前就會自行退出了。 -This may seem drastic, -but it's very convenient. -If your program needs to read that file and can't do anything if the file doesn't exist, -exiting is a valid strategy. -There's even a shortcut method on `Result`s, called `unwrap`: +這種做法看起來有些極端,卻是十分實用的。 +如果你的程式需要讀取一個文件, 並且在文件不存在時無法執行任何操作,那麼退出是十分合理、有效的選擇。 +在 `Result` 中還有一個快捷方法,叫做 `unwrap`: ```rust,no_run let content = std::fs::read_to_string("test.txt").unwrap(); ``` -## No need to panic +## 無須 panic -Of course, aborting the program is not the only way to deal with errors. -Instead of the `panic!`, we can also easily write `return`: +當然,退出程式並非處理錯誤的唯一辦法。 + +除 `panic!`之外,實作 `return` 也很簡單: ```rust,no_run # fn main() -> Result<(), Box> { @@ -89,12 +85,10 @@ let content = match result { # } ``` -This, however changes the return type our function needs. -Indeed, there was something hidden in our examples all this time: -The function signature this code lives in. -And in this last example with `return`, -it becomes important. -Here's the _full_ example: +然而,這改變了我們函數的回傳值類型。 +實際上,一直以來我們的範例都隱藏了一些東西: 函數的簽名(或說回傳值型別)。 +在最後的含有 `return` 的範例中,它變得很重要了。 +下面是 _完整_ 的範例: ```rust,no_run fn main() -> Result<(), Box> { @@ -108,15 +102,14 @@ fn main() -> Result<(), Box> { } ``` -Our return type is a `Result`! -This is why we can write `return Err(error);` in the second match arm. -See how there is an `Ok(())` at the bottom? -It's the default return value of the function and means -"Result is okay, and has no content". +我們的回傳值類型是 `Result`! +這也就是為什麼我們可以在 `match` 的第二個分支寫 `return Err(error);`。 +看到最下面的 Ok(()) 是什麼嗎? +它是函數的預設回傳值, 意思為「結果沒問題,沒有內容」。