diff --git a/Cargo.lock b/Cargo.lock index 84e5bbf..35e08bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -235,6 +235,17 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "auto_impl" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "autocfg" version = "1.4.0" @@ -269,7 +280,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper 1.0.2", "tokio", - "tower", + "tower 0.5.2", "tower-layer", "tower-service", "tracing", @@ -572,6 +583,7 @@ dependencies = [ "cooklang", "cooklang-find 0.5.0", "cooklang-import", + "cooklang-language-server", "cooklang-reports", "directories", "fluent", @@ -597,8 +609,9 @@ dependencies = [ "textwrap", "tokio", "toml 0.9.5", - "tower", + "tower 0.5.2", "tower-http 0.5.2", + "tower-lsp", "tracing", "tracing-subscriber", "unic-langid", @@ -616,10 +629,14 @@ dependencies = [ "codesnake", "enum-map", "finl_unicode", + "prettyplease", + "proc-macro2", + "quote", "serde", "serde_yaml", "smallvec", "strum", + "syn", "thiserror 2.0.12", "toml 0.8.23", "tracing", @@ -675,6 +692,27 @@ dependencies = [ "tokio", ] +[[package]] +name = "cooklang-language-server" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5589a2a285d563904cd12348dca1f848c043ec558c5e9cf267746bb0395d077f" +dependencies = [ + "anyhow", + "cooklang", + "dashmap 6.1.0", + "nohash-hasher", + "ropey", + "serde", + "serde_json", + "text-size", + "thiserror 2.0.12", + "tokio", + "tower-lsp", + "tracing", + "tracing-subscriber", +] + [[package]] name = "cooklang-reports" version = "0.2.0" @@ -816,6 +854,33 @@ dependencies = [ "syn", ] +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + [[package]] name = "der" version = "0.7.10" @@ -1223,6 +1288,20 @@ dependencies = [ "new_debug_unreachable", ] +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.31" @@ -1245,6 +1324,17 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "futures-sink" version = "0.3.31" @@ -1263,8 +1353,10 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ + "futures-channel", "futures-core", "futures-io", + "futures-macro", "futures-sink", "futures-task", "memchr", @@ -2007,6 +2099,19 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +[[package]] +name = "lsp-types" +version = "0.94.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66bfd44a06ae10647fe3f8214762e9369fd4248df1350924b4ef9e770a85ea1" +dependencies = [ + "bitflags 1.3.2", + "serde", + "serde_json", + "serde_repr", + "url", +] + [[package]] name = "mac" version = "0.1.1" @@ -2123,6 +2228,12 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + [[package]] name = "nom" version = "7.1.3" @@ -2433,6 +2544,26 @@ dependencies = [ "siphasher 1.0.1", ] +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "pin-project-lite" version = "0.2.16" @@ -2536,6 +2667,16 @@ dependencies = [ "termtree", ] +[[package]] +name = "prettyplease" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6837b9e10d61f45f987d50808f83d1ee3d206c66acf650c3e4ae2e1f6ddedf55" +dependencies = [ + "proc-macro2", + "syn", +] + [[package]] name = "proc-macro-hack" version = "0.5.20+deprecated" @@ -2816,7 +2957,7 @@ dependencies = [ "tokio", "tokio-native-tls", "tokio-rustls", - "tower", + "tower 0.5.2", "tower-http 0.6.4", "tower-service", "url", @@ -2852,6 +2993,16 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "ropey" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93411e420bcd1a75ddd1dc3caf18c23155eda2c090631a85af21ba19e97093b5" +dependencies = [ + "smallvec", + "str_indices", +] + [[package]] name = "rust-embed" version = "8.7.2" @@ -3172,6 +3323,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "serde_spanned" version = "0.6.9" @@ -3343,6 +3505,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "str_indices" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d08889ec5408683408db66ad89e0e1f93dff55c73a4ccc71c427d5b277ee47e6" + [[package]] name = "string_cache" version = "0.8.9" @@ -3560,6 +3728,12 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" +[[package]] +name = "text-size" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233" + [[package]] name = "textwrap" version = "0.16.2" @@ -3817,6 +3991,20 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc842091f2def52017664b53082ecbbeb5c7731092bad69d2c63050401dfd64" +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tower-layer", + "tower-service", +] + [[package]] name = "tower" version = "0.5.2" @@ -3871,7 +4059,7 @@ dependencies = [ "http-body 1.0.1", "iri-string", "pin-project-lite", - "tower", + "tower 0.5.2", "tower-layer", "tower-service", ] @@ -3882,6 +4070,40 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" +[[package]] +name = "tower-lsp" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ba052b54a6627628d9b3c34c176e7eda8359b7da9acd497b9f20998d118508" +dependencies = [ + "async-trait", + "auto_impl", + "bytes", + "dashmap 5.5.3", + "futures", + "httparse", + "lsp-types", + "memchr", + "serde", + "serde_json", + "tokio", + "tokio-util", + "tower 0.4.13", + "tower-lsp-macros", + "tracing", +] + +[[package]] +name = "tower-lsp-macros" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84fd902d4e0b9a4b27f2f440108dc034e1758628a9b702f8ec61ad66355422fa" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tower-service" version = "0.3.3" @@ -4077,6 +4299,7 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index d21faf7..830d3df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,6 +39,7 @@ clap = { version = "4.5", features = ["derive"] } cooklang = { version = "0.17.4", default-features = false, features = ["aisle", "pantry"] } cooklang-find = { version = "0.5.0" } cooklang-import = "0.8.7" +cooklang-language-server = "0.1.0" cooklang-reports = { version = "0.2" } directories = "6" fluent = "0.16" @@ -61,6 +62,7 @@ tokio = { version = "1", features = ["full"] } toml = "0.9.5" tower = { version = "0.5", features = ["util"] } tower-http = { version = "0.5", features = ["fs", "trace", "cors"] } +tower-lsp = "0.20" tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } unic-langid = "0.9" diff --git a/docs/lsp.md b/docs/lsp.md new file mode 100644 index 0000000..9bcdeaa --- /dev/null +++ b/docs/lsp.md @@ -0,0 +1,259 @@ +# LSP Command + +The `lsp` command starts a Language Server Protocol (LSP) server for Cooklang recipe files. It enables IDE features in text editors and development environments. + +## Overview + +The LSP server provides intelligent editing features for `.cook` files: + +- **Real-time syntax checking** – Catch errors as you type +- **Auto-completion** – Suggestions for ingredients, cookware, and timers +- **Semantic highlighting** – Rich syntax coloring beyond basic highlighting +- **Hover documentation** – Information about ingredients and references +- **Document symbols** – Navigate recipe structure quickly +- **Go to definition** – Jump to referenced recipes + +## Basic Usage + +Start the LSP server: +```bash +cook lsp +``` + +The server communicates over stdin/stdout using the standard LSP protocol. You typically don't run this command directly—your editor starts it automatically. + +## Editor Integration + +### Visual Studio Code + +Install the [Cooklang extension](https://marketplace.visualstudio.com/items?itemName=cooklang.cooklang) from the VS Code marketplace. The extension automatically uses `cook lsp` when available. + +**Manual Configuration:** + +Add to your `settings.json`: +```json +{ + "cooklang.languageServer.path": "cook", + "cooklang.languageServer.args": ["lsp"] +} +``` + +### Neovim + +Using [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig): + +```lua +local lspconfig = require('lspconfig') +local configs = require('lspconfig.configs') + +if not configs.cooklang then + configs.cooklang = { + default_config = { + cmd = { 'cook', 'lsp' }, + filetypes = { 'cooklang' }, + root_dir = lspconfig.util.root_pattern('.git', 'config'), + settings = {}, + }, + } +end + +lspconfig.cooklang.setup{} +``` + +### Vim with CoC + +Add to your `coc-settings.json`: +```json +{ + "languageserver": { + "cooklang": { + "command": "cook", + "args": ["lsp"], + "filetypes": ["cooklang"], + "rootPatterns": [".git", "config"] + } + } +} +``` + +### Emacs + +Using [lsp-mode](https://emacs-lsp.github.io/lsp-mode/): + +```elisp +(with-eval-after-load 'lsp-mode + (add-to-list 'lsp-language-id-configuration + '(cooklang-mode . "cooklang")) + + (lsp-register-client + (make-lsp-client + :new-connection (lsp-stdio-connection '("cook" "lsp")) + :activation-fn (lsp-activate-on "cooklang") + :server-id 'cooklang-lsp))) +``` + +Using [eglot](https://github.com/joaotavora/eglot): + +```elisp +(add-to-list 'eglot-server-programs + '(cooklang-mode . ("cook" "lsp"))) +``` + +### Helix + +Add to your `languages.toml`: +```toml +[[language]] +name = "cooklang" +scope = "source.cooklang" +file-types = ["cook"] +language-servers = ["cooklang-lsp"] + +[language-server.cooklang-lsp] +command = "cook" +args = ["lsp"] +``` + +### Sublime Text + +Using [LSP package](https://github.com/sublimelsp/LSP): + +Add to LSP settings: +```json +{ + "clients": { + "cooklang": { + "enabled": true, + "command": ["cook", "lsp"], + "selector": "source.cooklang" + } + } +} +``` + +### Zed + +Add to your `settings.json`: +```json +{ + "lsp": { + "cooklang": { + "binary": { + "path": "cook", + "arguments": ["lsp"] + } + } + } +} +``` + +## Features + +### Diagnostics + +The LSP server reports syntax errors and warnings in real-time: + +``` +Line 5: Invalid ingredient syntax - missing quantity +Line 8: Timer format should be ~{time%unit} +Line 12: Referenced recipe not found: ./Missing Recipe.cook +``` + +### Completions + +Auto-completion triggers in various contexts: + +- **Ingredients** – After typing `@`, suggests known ingredients +- **Cookware** – After typing `#`, suggests equipment +- **Timers** – After typing `~`, suggests time formats +- **References** – Suggests recipe files for `@./` paths +- **Metadata** – Suggests common metadata keys in frontmatter + +### Hover Information + +Hover over elements to see details: + +- **Ingredients** – Quantity, unit, and any notes +- **Timers** – Formatted duration +- **Recipe references** – Preview of referenced recipe +- **Metadata** – Description of metadata fields + +### Document Symbols + +Navigate recipe structure: + +- Sections and steps +- Ingredients list +- Cookware list +- Timers +- Metadata fields + +### Semantic Tokens + +Enhanced syntax highlighting for: + +- Ingredients (with quantity and unit distinction) +- Cookware +- Timers +- Comments +- Metadata keys and values +- Recipe references + +## Troubleshooting + +### Server Not Starting + +Verify the cook command is in your PATH: +```bash +which cook +cook --version +``` + +### Connection Issues + +Check server logs by running manually: +```bash +cook lsp 2>/tmp/cooklang-lsp.log +``` + +### Editor Not Detecting Server + +Ensure your editor: +1. Recognizes `.cook` files as Cooklang +2. Has LSP client support enabled +3. Is configured with the correct command path + +### Debugging + +Enable verbose logging: +```bash +RUST_LOG=debug cook lsp 2>/tmp/cooklang-lsp-debug.log +``` + +## Protocol Details + +The server implements LSP specification features: + +| Feature | Support | +|---------|---------| +| textDocument/didOpen | Yes | +| textDocument/didChange | Yes | +| textDocument/didClose | Yes | +| textDocument/completion | Yes | +| textDocument/hover | Yes | +| textDocument/definition | Yes | +| textDocument/documentSymbol | Yes | +| textDocument/semanticTokens | Yes | +| textDocument/publishDiagnostics | Yes | + +### Transport + +- **Protocol**: JSON-RPC 2.0 +- **Transport**: stdin/stdout +- **Encoding**: UTF-8 + +## See Also + +- [Language Server Protocol Specification](https://microsoft.github.io/language-server-protocol/) +- [Cooklang Syntax Reference](https://cooklang.org/docs/spec/) +- [Editor Integrations](https://cooklang.org/cli/editors/) diff --git a/src/args.rs b/src/args.rs index d039899..b8d7372 100644 --- a/src/args.rs +++ b/src/args.rs @@ -32,7 +32,7 @@ use clap::{Parser, Subcommand}; #[cfg(feature = "self-update")] use crate::update; -use crate::{doctor, import, pantry, recipe, report, search, seed, server, shopping_list}; +use crate::{doctor, import, lsp, pantry, recipe, report, search, seed, server, shopping_list}; #[derive(Parser, Debug)] #[command( @@ -193,6 +193,26 @@ pub enum Command { )] Pantry(pantry::PantryArgs), + /// Start the Cooklang Language Server Protocol (LSP) server + /// + /// Launches an LSP server that provides IDE features for Cooklang recipe files. + /// The server communicates over stdin/stdout using the standard LSP protocol, + /// enabling integration with editors like VS Code, Neovim, Emacs, and others. + /// + /// Features include: + /// - Real-time syntax checking and validation + /// - Auto-completion for ingredients, cookware, and timers + /// - Semantic syntax highlighting + /// - Hover documentation + /// - Document symbols and navigation + /// + /// Examples: + /// cook lsp # Start the LSP server + #[command( + long_about = "Start the Language Server Protocol server for Cooklang editor integration" + )] + Lsp(lsp::LspArgs), + /// Update CookCLI to the latest version /// /// Checks for new releases on GitHub and automatically downloads and diff --git a/src/lib.rs b/src/lib.rs index ec79a82..57cb582 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,7 @@ use camino::Utf8PathBuf; // Commands - make them available as public modules pub mod doctor; pub mod import; +pub mod lsp; pub mod pantry; pub mod recipe; pub mod report; diff --git a/src/lsp.rs b/src/lsp.rs new file mode 100644 index 0000000..cb9991d --- /dev/null +++ b/src/lsp.rs @@ -0,0 +1,51 @@ +use anyhow::Result; +use clap::Args; +use cooklang_language_server::Backend; +use tower_lsp::{LspService, Server}; +use tracing::{debug, info}; + +use crate::Context; + +#[derive(Debug, Args)] +#[command()] +pub struct LspArgs {} + +/// Start the Cooklang Language Server Protocol server. +/// +/// Note: The LSP server receives workspace configuration from the editor during +/// the LSP initialization handshake. The editor sends workspace folders, and the +/// server loads aisle.conf from those locations. The Context paths logged below +/// are for debugging and future extensibility when the upstream cooklang-language-server +/// crate supports custom configuration paths. +#[tokio::main] +pub async fn run(ctx: &Context, _args: LspArgs) -> Result<()> { + info!("Starting Cooklang LSP server"); + + // Log available configuration paths for debugging + // Currently the LSP server uses workspace paths from the editor, + // but these could be used in the future for global config support + debug!("Base path: {}", ctx.base_path()); + if let Some(aisle) = ctx.aisle() { + debug!("Aisle config: {}", aisle); + } + if let Some(pantry) = ctx.pantry() { + debug!("Pantry config: {}", pantry); + } + + let stdin = tokio::io::stdin(); + let stdout = tokio::io::stdout(); + + let (service, socket) = LspService::new(Backend::new); + + // Use tokio::select! to handle both the LSP server and shutdown signals + tokio::select! { + _ = Server::new(stdin, stdout, socket).serve(service) => { + info!("LSP server stopped"); + } + _ = tokio::signal::ctrl_c() => { + info!("Received shutdown signal, stopping LSP server"); + } + } + + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index 8d676c5..0981902 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,6 +37,7 @@ use clap::Parser; // commands mod doctor; mod import; +mod lsp; mod pantry; mod recipe; mod report; @@ -73,6 +74,7 @@ pub fn main() -> Result<()> { Command::Report(args) => report::run(&ctx, args), Command::Doctor(args) => doctor::run(&ctx, args), Command::Pantry(args) => pantry::run(&ctx, args), + Command::Lsp(args) => lsp::run(&ctx, args), #[cfg(feature = "self-update")] Command::Update(args) => update::run(args), } diff --git a/tests/snapshots/snapshot_test__help_output.snap b/tests/snapshots/snapshot_test__help_output.snap index ae77693..ef61c38 100644 --- a/tests/snapshots/snapshot_test__help_output.snap +++ b/tests/snapshots/snapshot_test__help_output.snap @@ -1,5 +1,6 @@ --- source: tests/snapshot_test.rs +assertion_line: 311 expression: stdout --- A command-line interface for managing and working with Cooklang recipes @@ -16,6 +17,7 @@ Commands: report Generate custom reports from recipes using templates doctor Analyze your recipe collection for issues and improvements pantry Manage and analyze your pantry inventory + lsp Start the Cooklang Language Server Protocol (LSP) server update Update CookCLI to the latest version help Print this message or the help of the given subcommand(s) diff --git a/tests/snapshots/snapshot_test__help_output_no_update.snap b/tests/snapshots/snapshot_test__help_output_no_update.snap index a5e45af..a991815 100644 --- a/tests/snapshots/snapshot_test__help_output_no_update.snap +++ b/tests/snapshots/snapshot_test__help_output_no_update.snap @@ -17,6 +17,7 @@ Commands: report Generate custom reports from recipes using templates doctor Analyze your recipe collection for issues and improvements pantry Manage and analyze your pantry inventory + lsp Start the Cooklang Language Server Protocol (LSP) server help Print this message or the help of the given subcommand(s) Options: diff --git a/tests/snapshots/snapshot_test__recipe_human_output.snap b/tests/snapshots/snapshot_test__recipe_human_output.snap index 11a71e0..b8e4826 100644 --- a/tests/snapshots/snapshot_test__recipe_human_output.snap +++ b/tests/snapshots/snapshot_test__recipe_human_output.snap @@ -1,5 +1,6 @@ --- source: tests/snapshot_test.rs +assertion_line: 24 expression: stdout --- Simple Recipe @@ -7,9 +8,9 @@ expression: stdout servings: 2 Ingredients: - pasta 200 g - salt 1 tsp - water 2 cups + pasta 200 g + salt 1 tsp + water 2 c Cookware: pot @@ -17,4 +18,4 @@ Cookware: Steps: 1. Boil water for 5 minutes. Add salt and pasta. Cook in a pot for another 10 minutes. - [water: 2 cups, salt: 1 tsp, pasta: 200 g] + [water: 2 c, salt: 1 tsp, pasta: 200 g] diff --git a/tests/snapshots/snapshot_test__recipe_json_output.snap b/tests/snapshots/snapshot_test__recipe_json_output.snap index ef39864..a26fe8d 100644 --- a/tests/snapshots/snapshot_test__recipe_json_output.snap +++ b/tests/snapshots/snapshot_test__recipe_json_output.snap @@ -1,5 +1,6 @@ --- source: tests/snapshot_test.rs +assertion_line: 50 expression: formatted --- { @@ -24,8 +25,8 @@ expression: formatted "name": "water", "note": null, "quantity": { - "scalable": true, - "unit": "cups", + "scalable": false, + "unit": "c", "value": { "type": "number", "value": { @@ -50,7 +51,7 @@ expression: formatted "name": "salt", "note": null, "quantity": { - "scalable": true, + "scalable": false, "unit": "tsp", "value": { "type": "number", @@ -76,7 +77,7 @@ expression: formatted "name": "pasta", "note": null, "quantity": { - "scalable": true, + "scalable": false, "unit": "g", "value": { "type": "number", diff --git a/tests/snapshots/snapshot_test__recipe_markdown_output.snap b/tests/snapshots/snapshot_test__recipe_markdown_output.snap index b8af99e..5b7db28 100644 --- a/tests/snapshots/snapshot_test__recipe_markdown_output.snap +++ b/tests/snapshots/snapshot_test__recipe_markdown_output.snap @@ -1,5 +1,6 @@ --- source: tests/snapshot_test.rs +assertion_line: 92 expression: stdout --- --- @@ -12,8 +13,8 @@ name: Pancakes ## Ingredients -- *2 cups* flour -- *1.5 cups* milk +- *2 c* flour +- *1 1/2 c* milk - *2* eggs - *2 tbsp* sugar diff --git a/tests/snapshots/snapshot_test__recipe_yaml_output.snap b/tests/snapshots/snapshot_test__recipe_yaml_output.snap index c433568..4798627 100644 --- a/tests/snapshots/snapshot_test__recipe_yaml_output.snap +++ b/tests/snapshots/snapshot_test__recipe_yaml_output.snap @@ -1,5 +1,6 @@ --- source: tests/snapshot_test.rs +assertion_line: 71 expression: stdout --- metadata: @@ -48,8 +49,8 @@ ingredients: value: type: regular value: 2.0 - unit: cups - scalable: true + unit: c + scalable: false note: null reference: null relation: @@ -68,7 +69,7 @@ ingredients: type: regular value: 1.0 unit: tsp - scalable: true + scalable: false note: null reference: null relation: @@ -87,7 +88,7 @@ ingredients: type: regular value: 200.0 unit: g - scalable: true + scalable: false note: null reference: null relation: diff --git a/tests/snapshots/snapshot_test__scaled_recipe_output.snap b/tests/snapshots/snapshot_test__scaled_recipe_output.snap index 14eaa9f..9bcb3cd 100644 --- a/tests/snapshots/snapshot_test__scaled_recipe_output.snap +++ b/tests/snapshots/snapshot_test__scaled_recipe_output.snap @@ -1,5 +1,6 @@ --- source: tests/snapshot_test.rs +assertion_line: 289 expression: formatted --- { @@ -24,8 +25,8 @@ expression: formatted "name": "water", "note": null, "quantity": { - "scalable": true, - "unit": "cups", + "scalable": false, + "unit": "c", "value": { "type": "number", "value": { @@ -50,13 +51,18 @@ expression: formatted "name": "salt", "note": null, "quantity": { - "scalable": true, - "unit": "tsp", + "scalable": false, + "unit": "tbsp", "value": { "type": "number", "value": { - "type": "regular", - "value": 3.0 + "type": "fraction", + "value": { + "den": 1, + "err": -6.762804893867269e-8, + "num": 0, + "whole": 1 + } } } }, @@ -76,7 +82,7 @@ expression: formatted "name": "pasta", "note": null, "quantity": { - "scalable": true, + "scalable": false, "unit": "g", "value": { "type": "number",