From daa7e5b195e6309810d2b4ddf198573f06d98cb4 Mon Sep 17 00:00:00 2001 From: Sebastian Lorenz Date: Mon, 3 Aug 2026 05:53:17 +0000 Subject: [PATCH 1/2] Add reproduction for cli/internal/lexer issue --- .../unstable/cli/LexerInlineEquals.audit.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 packages/effect/test/unstable/cli/LexerInlineEquals.audit.test.ts diff --git a/packages/effect/test/unstable/cli/LexerInlineEquals.audit.test.ts b/packages/effect/test/unstable/cli/LexerInlineEquals.audit.test.ts new file mode 100644 index 00000000000..6fdd1022b4b --- /dev/null +++ b/packages/effect/test/unstable/cli/LexerInlineEquals.audit.test.ts @@ -0,0 +1,13 @@ +import { assert, it } from "@effect/vitest" +import * as Lexer from "effect/unstable/cli/internal/lexer" + +it("preserves every equals sign in a long option's inline value", () => { + const result = Lexer.lex(["--query=left=right"]) + + assert.deepStrictEqual(result.tokens, [{ + _tag: "LongOption", + name: "query", + raw: "--query=left=right", + value: "left=right" + }]) +}) From b29704e2af474f4af9e7dd7b3a392f18a2c9f5e7 Mon Sep 17 00:00:00 2001 From: Tim Smart Date: Tue, 4 Aug 2026 09:27:51 +1200 Subject: [PATCH 2/2] Fix inline CLI option values --- .changeset/calm-tools-remember.md | 5 +++++ .../effect/src/unstable/cli/internal/lexer.ts | 10 ++++++++-- packages/effect/test/unstable/cli/Lexer.test.ts | 15 +++++++++++++++ .../unstable/cli/LexerInlineEquals.audit.test.ts | 13 ------------- 4 files changed, 28 insertions(+), 15 deletions(-) create mode 100644 .changeset/calm-tools-remember.md create mode 100644 packages/effect/test/unstable/cli/Lexer.test.ts delete mode 100644 packages/effect/test/unstable/cli/LexerInlineEquals.audit.test.ts diff --git a/.changeset/calm-tools-remember.md b/.changeset/calm-tools-remember.md new file mode 100644 index 00000000000..3fdf6410e03 --- /dev/null +++ b/.changeset/calm-tools-remember.md @@ -0,0 +1,5 @@ +--- +"effect": patch +--- + +Preserve equals signs in inline CLI option values after the first separator. diff --git a/packages/effect/src/unstable/cli/internal/lexer.ts b/packages/effect/src/unstable/cli/internal/lexer.ts index 3d09d117718..40e47641bbf 100644 --- a/packages/effect/src/unstable/cli/internal/lexer.ts +++ b/packages/effect/src/unstable/cli/internal/lexer.ts @@ -47,8 +47,14 @@ const lexTokens = (args: ReadonlyArray): ReadonlyArray => { if (!arg.startsWith("-")) { tokens.push({ _tag: "Value", value: arg }) } else if (arg.startsWith("--")) { - const [name, value] = arg.slice(2).split("=", 2) - tokens.push({ _tag: "LongOption", name, raw: arg, value }) + const equalIndex = arg.indexOf("=") + if (equalIndex !== -1) { + const name = arg.slice(2, equalIndex) + const value = arg.slice(equalIndex + 1) + tokens.push({ _tag: "LongOption", name, raw: arg, value }) + } else { + tokens.push({ _tag: "LongOption", name: arg.slice(2), raw: arg }) + } } else if (arg.length > 1) { const flags = arg.slice(1) const equalIndex = flags.indexOf("=") diff --git a/packages/effect/test/unstable/cli/Lexer.test.ts b/packages/effect/test/unstable/cli/Lexer.test.ts new file mode 100644 index 00000000000..7d55f26815e --- /dev/null +++ b/packages/effect/test/unstable/cli/Lexer.test.ts @@ -0,0 +1,15 @@ +import { assert, describe, it } from "@effect/vitest" +import * as Lexer from "effect/unstable/cli/internal/lexer" + +describe("Lexer", () => { + it("preserves every equals sign in a long option's inline value", () => { + const result = Lexer.lex(["--query=left=right"]) + + assert.deepStrictEqual(result.tokens, [{ + _tag: "LongOption", + name: "query", + raw: "--query=left=right", + value: "left=right" + }]) + }) +}) diff --git a/packages/effect/test/unstable/cli/LexerInlineEquals.audit.test.ts b/packages/effect/test/unstable/cli/LexerInlineEquals.audit.test.ts deleted file mode 100644 index 6fdd1022b4b..00000000000 --- a/packages/effect/test/unstable/cli/LexerInlineEquals.audit.test.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { assert, it } from "@effect/vitest" -import * as Lexer from "effect/unstable/cli/internal/lexer" - -it("preserves every equals sign in a long option's inline value", () => { - const result = Lexer.lex(["--query=left=right"]) - - assert.deepStrictEqual(result.tokens, [{ - _tag: "LongOption", - name: "query", - raw: "--query=left=right", - value: "left=right" - }]) -})