From fc9a92502cbbbfb728d3be1f2aaef9fd4699efce Mon Sep 17 00:00:00 2001 From: Milind Sharma Date: Fri, 20 Feb 2026 14:16:56 +0800 Subject: [PATCH] feat(project): add ExpandTextVariables API bindings --- README.md | 6 ++--- docs/TEST_CLI.md | 6 +++++ src/client.rs | 27 +++++++++++++++++++++ test-scripts/kicad-ipc-cli.rs | 44 ++++++++++++++++++++++++++++++++++- 4 files changed, 79 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9355335..233f428 100644 --- a/README.md +++ b/README.md @@ -40,10 +40,10 @@ Legend: | --- | ---: | ---: | ---: | | Common (base) | 6 | 2 | 33% | | Common editor/document | 23 | 9 | 39% | -| Project manager | 5 | 2 | 40% | +| Project manager | 5 | 3 | 60% | | Board editor (PCB) | 22 | 13 | 59% | | Schematic editor (dedicated proto commands) | 0 | 0 | n/a | -| **Total** | **56** | **26** | **46%** | +| **Total** | **56** | **27** | **48%** | ### Common (base) @@ -90,7 +90,7 @@ Legend: | --- | --- | --- | | `GetNetClasses` | Implemented | `KiCadClient::get_net_classes_raw`, `KiCadClient::get_net_classes` | | `SetNetClasses` | Not yet | - | -| `ExpandTextVariables` | Not yet | - | +| `ExpandTextVariables` | Implemented | `KiCadClient::expand_text_variables_raw`, `KiCadClient::expand_text_variables` | | `GetTextVariables` | Implemented | `KiCadClient::get_text_variables_raw`, `KiCadClient::get_text_variables` | | `SetTextVariables` | Not yet | - | diff --git a/docs/TEST_CLI.md b/docs/TEST_CLI.md index 66736ed..f2c3cf1 100644 --- a/docs/TEST_CLI.md +++ b/docs/TEST_CLI.md @@ -59,6 +59,12 @@ List text variables for current board document: cargo run --bin kicad-ipc-cli -- text-variables ``` +Expand text variables in one or more input strings: + +```bash +cargo run --bin kicad-ipc-cli -- expand-text-variables --text "${TITLE}" --text "${REVISION}" +``` + List enabled board layers: ```bash diff --git a/src/client.rs b/src/client.rs index 3193d48..e69af24 100644 --- a/src/client.rs +++ b/src/client.rs @@ -37,6 +37,7 @@ const CMD_PING: &str = "kiapi.common.commands.Ping"; const CMD_GET_VERSION: &str = "kiapi.common.commands.GetVersion"; const CMD_GET_NET_CLASSES: &str = "kiapi.common.commands.GetNetClasses"; const CMD_GET_TEXT_VARIABLES: &str = "kiapi.common.commands.GetTextVariables"; +const CMD_EXPAND_TEXT_VARIABLES: &str = "kiapi.common.commands.ExpandTextVariables"; const CMD_GET_OPEN_DOCUMENTS: &str = "kiapi.common.commands.GetOpenDocuments"; const CMD_GET_NETS: &str = "kiapi.board.commands.GetNets"; const CMD_GET_BOARD_ENABLED_LAYERS: &str = "kiapi.board.commands.GetBoardEnabledLayers"; @@ -65,6 +66,8 @@ const CMD_SAVE_SELECTION_TO_STRING: &str = "kiapi.common.commands.SaveSelectionT const RES_GET_VERSION: &str = "kiapi.common.commands.GetVersionResponse"; const RES_NET_CLASSES_RESPONSE: &str = "kiapi.common.commands.NetClassesResponse"; const RES_TEXT_VARIABLES: &str = "kiapi.common.project.TextVariables"; +const RES_EXPAND_TEXT_VARIABLES_RESPONSE: &str = + "kiapi.common.commands.ExpandTextVariablesResponse"; const RES_GET_OPEN_DOCUMENTS: &str = "kiapi.common.commands.GetOpenDocumentsResponse"; const RES_GET_NETS: &str = "kiapi.board.commands.NetsResponse"; const RES_GET_BOARD_ENABLED_LAYERS: &str = "kiapi.board.commands.BoardEnabledLayersResponse"; @@ -359,6 +362,30 @@ impl KiCadClient { Ok(response.variables.into_iter().collect()) } + pub async fn expand_text_variables_raw( + &self, + text: Vec, + ) -> Result { + let command = common_commands::ExpandTextVariables { + document: Some(self.current_board_document_proto().await?), + text, + }; + let response = self + .send_command(envelope::pack_any(&command, CMD_EXPAND_TEXT_VARIABLES)) + .await?; + response_payload_as_any(response, RES_EXPAND_TEXT_VARIABLES_RESPONSE) + } + + pub async fn expand_text_variables( + &self, + text: Vec, + ) -> Result, KiCadError> { + let payload = self.expand_text_variables_raw(text).await?; + let response: common_commands::ExpandTextVariablesResponse = + decode_any(&payload, RES_EXPAND_TEXT_VARIABLES_RESPONSE)?; + Ok(response.text) + } + pub async fn get_current_project_path(&self) -> Result { let docs = self.get_open_documents(DocumentType::Pcb).await?; select_single_project_path(&docs) diff --git a/test-scripts/kicad-ipc-cli.rs b/test-scripts/kicad-ipc-cli.rs index 6c9b39b..f0d0795 100644 --- a/test-scripts/kicad-ipc-cli.rs +++ b/test-scripts/kicad-ipc-cli.rs @@ -34,6 +34,9 @@ enum Command { BoardOpen, NetClasses, TextVariables, + ExpandTextVariables { + text: Vec, + }, Nets, EnabledLayers, ActiveLayer, @@ -204,6 +207,13 @@ async fn run() -> Result<(), KiCadError> { println!("name={} value={}", name, value); } } + Command::ExpandTextVariables { text } => { + let expanded = client.expand_text_variables(text.clone()).await?; + println!("expanded_count={}", expanded.len()); + for (index, value) in expanded.iter().enumerate() { + println!("[{index}] input={} expanded={}", text[index], value); + } + } Command::Nets => { let nets = client.get_nets().await?; if nets.is_empty() { @@ -598,6 +608,33 @@ fn parse_args() -> Result<(CliConfig, Command), KiCadError> { "board-open" => Command::BoardOpen, "net-classes" => Command::NetClasses, "text-variables" => Command::TextVariables, + "expand-text-variables" => { + let mut text = Vec::new(); + let mut i = 1; + while i < args.len() { + match args[i].as_str() { + "--text" => { + let value = args.get(i + 1).ok_or_else(|| KiCadError::Config { + reason: "missing value for expand-text-variables --text".to_string(), + })?; + text.push(value.clone()); + i += 2; + } + _ => { + i += 1; + } + } + } + + if text.is_empty() { + return Err(KiCadError::Config { + reason: "expand-text-variables requires one or more `--text ` arguments" + .to_string(), + }); + } + + Command::ExpandTextVariables { text } + } "nets" => Command::Nets, "enabled-layers" => Command::EnabledLayers, "active-layer" => Command::ActiveLayer, @@ -933,7 +970,7 @@ fn default_config() -> CliConfig { fn print_help() { println!( - "kicad-ipc-cli\n\nUSAGE:\n cargo run --bin kicad-ipc-cli -- [--socket URI] [--token TOKEN] [--timeout-ms N] [command options]\n\nCOMMANDS:\n ping Check IPC connectivity\n version Fetch KiCad version\n open-docs [--type ] List open docs (default type: pcb)\n project-path Get current project path from open PCB docs\n board-open Exit non-zero if no PCB doc is open\n net-classes List project netclass definitions\n text-variables List text variables for current board document\n nets List board nets (requires one open PCB)\n netlist-pads Emit pad-level netlist data (with footprint context)\n items-by-id --id ... Show parsed details for specific item IDs\n item-bbox --id ... Show bounding boxes for item IDs\n hit-test --id --x-nm --y-nm [--tolerance-nm ]\n Hit-test one item at a point\n types-pcb List PCB KiCad object type IDs from proto enum\n items-raw --type-id ... Dump raw Any payloads for requested item type IDs\n items-raw-all-pcb [--debug] Dump all PCB item payloads across all PCB object types\n pad-shape-polygon --pad-id ... --layer-id [--debug]\n Dump pad polygons on a target layer\n padstack-presence --item-id ... --layer-id ... [--debug]\n Check padstack shape presence matrix across layers\n title-block Show title block fields\n board-as-string Dump board as KiCad s-expression text\n selection-as-string Dump current selection as KiCad s-expression text\n stackup Show typed board stackup\n graphics-defaults Show typed graphics defaults\n appearance Show typed editor appearance settings\n netclass Show typed netclass map for current board nets\n proto-coverage-board-read Print board-read command coverage vs proto\n board-read-report [--out P] Write markdown board reconstruction report\n enabled-layers List enabled board layers\n active-layer Show active board layer\n visible-layers Show currently visible board layers\n board-origin [--type ] Show board origin (`grid` default, or `drill`)\n selection-summary Show current selection item type counts\n selection-details Show parsed details for selected items\n selection-raw Show raw Any payload bytes for selected items\n smoke ping + version + board-open summary\n help Show help\n\nTYPES:\n schematic | symbol | pcb | footprint | drawing-sheet | project\n" + "kicad-ipc-cli\n\nUSAGE:\n cargo run --bin kicad-ipc-cli -- [--socket URI] [--token TOKEN] [--timeout-ms N] [command options]\n\nCOMMANDS:\n ping Check IPC connectivity\n version Fetch KiCad version\n open-docs [--type ] List open docs (default type: pcb)\n project-path Get current project path from open PCB docs\n board-open Exit non-zero if no PCB doc is open\n net-classes List project netclass definitions\n text-variables List text variables for current board document\n expand-text-variables Expand variables in provided text values\n Options: --text (repeatable)\n nets List board nets (requires one open PCB)\n netlist-pads Emit pad-level netlist data (with footprint context)\n items-by-id --id ... Show parsed details for specific item IDs\n item-bbox --id ... Show bounding boxes for item IDs\n hit-test --id --x-nm --y-nm [--tolerance-nm ]\n Hit-test one item at a point\n types-pcb List PCB KiCad object type IDs from proto enum\n items-raw --type-id ... Dump raw Any payloads for requested item type IDs\n items-raw-all-pcb [--debug] Dump all PCB item payloads across all PCB object types\n pad-shape-polygon --pad-id ... --layer-id [--debug]\n Dump pad polygons on a target layer\n padstack-presence --item-id ... --layer-id ... [--debug]\n Check padstack shape presence matrix across layers\n title-block Show title block fields\n board-as-string Dump board as KiCad s-expression text\n selection-as-string Dump current selection as KiCad s-expression text\n stackup Show typed board stackup\n graphics-defaults Show typed graphics defaults\n appearance Show typed editor appearance settings\n netclass Show typed netclass map for current board nets\n proto-coverage-board-read Print board-read command coverage vs proto\n board-read-report [--out P] Write markdown board reconstruction report\n enabled-layers List enabled board layers\n active-layer Show active board layer\n visible-layers Show currently visible board layers\n board-origin [--type ] Show board origin (`grid` default, or `drill`)\n selection-summary Show current selection item type counts\n selection-details Show parsed details for selected items\n selection-raw Show raw Any payload bytes for selected items\n smoke ping + version + board-open summary\n help Show help\n\nTYPES:\n schematic | symbol | pcb | footprint | drawing-sheet | project\n" ); } @@ -1346,6 +1383,11 @@ fn proto_coverage_board_read_rows() -> Vec<(&'static str, &'static str, &'static "implemented", "get_text_variables_raw/get_text_variables", ), + ( + "kiapi.common.commands.ExpandTextVariables", + "implemented", + "expand_text_variables_raw/expand_text_variables", + ), ( "kiapi.common.commands.GetItems", "implemented",