- Home
- Categories
- Uncategorized
- Time for a new #introduction over here!!Hello everyone, I'm Mystic!
Time for a new #introduction over here!!Hello everyone, I'm Mystic!
-
Time for a new #introduction over here!!
Hello everyone, I'm Mystic! I'm an Artist and Vtuber (tho i mainly just share my art over here) with a passion for my OCs, Cute girls, and Elves ✨
I also watch a fuck ton of anime and will gladly yap about the silly little guys that live in my head at a moments notice
Comm Info: https://mysdriel.uwu.ai
Streams: https://www.twitch.tv/mysdriel
#DigitalArt #MastoArt #Illustration #イラスト -
undefined oblomov@sociale.network shared this topic on
Gli ultimi otto messaggi ricevuti dalla Federazione
-
When building CLI tools, shell completion usually treats each option in isolation. But sometimes valid values for one option depend on another—like branch names depending on which repository you're targeting.
Wrote about how I solved this in Optique, a type-safe CLI parser for TypeScript.
https://hackers.pub/@hongminhee/2026/optique-context-aware-cli-completion
-
@rl_dane I also work on a very large Perl project, and will continue to do so for maybe the rest of my days (I'm 25+ years in, why stop now?).
-
@rl_dane yes, actually, see my recent threads about Go. I use it 100% of the time for web apps when I have a choice, and have done so for the past couple of years (and a lot lately). I'm also porting my old stuff that I have control over that's in Python. I have grown tired of the beatings. If it has dependencies or needs to be packaged I'm not building it in Python.
But, I maintain a bunch of Python packages for my job, so it's not really a choice I have for the stuff I'm working on right now.
-
@rl_dane if only there were some middle ground. Alas, impossible.
-
It's a passion for tracebacks. Soul mates. Love at first sight.
-
I wish I loved anything as much as the Python community loves breaking backward compatibility.
-
@evan I don't think there's been any Canadian political leader who's received much hero worship — maybe Pierre Trudeau? They all have major flaws, Sir John A. notably so.
(I contrast this with the arguably blasphemous https://en.wikipedia.org/wiki/The_Apotheosis_of_Washington ; I can't even imagine anyone doing something similar for any Canadian politician.)
-
Consider Git's -C option:
git -C /path/to/repo checkout <TAB>When you hit <kbd>Tab</kbd>, Git completes branch names from /path/to/repo, not your
current directory. The completion is context-aware—it depends on the value of
another option.Most CLI parsers can't do this. They treat each option in isolation, so
completion for --branch has no way of knowing the --repo value. You end up
with two unpleasant choices: either show completions for all possible
branches across all repositories (useless), or give up on completion entirely
for these options.Optique 0.10.0 introduces a dependency system that solves this problem while
Static dependencies with or()
preserving full type safety.Optique already handles certain kinds of dependent options via the or()
import { flag, object, option, or, string } from "@optique/core"; const outputOptions = or( object({ json: flag("--json"), pretty: flag("--pretty"), }), object({ csv: flag("--csv"), delimiter: option("--delimiter", string()), }), );
combinator:TypeScript knows that if json is true, you'll have a pretty field, and if
csv is true, you'll have a delimiter field. The parser enforces this at
runtime, and shell completion will suggest --pretty only when --json is
present.This works well when the valid combinations are known at definition time. But
Runtime dependencies
it can't handle cases where valid values depend on runtime input—like
branch names that vary by repository.Common scenarios include:
A deployment CLI where --environment affects which services are available A database tool where --connection affects which tables can be completed A cloud CLI where --project affects which resources are shownIn each case, you can't know the valid values until you know what the user
The dependency system
typed for the dependency option. Optique 0.10.0 introduces dependency() and
derive() to handle exactly this.The core idea is simple: mark one option as a dependency source, then create
import { choice, dependency, message, object, option, string, } from "@optique/core"; function getRefsFromRepo(repoPath: string): string[] { // In real code, this would read from the Git repository return ["main", "develop", "feature/login"]; } // Mark as a dependency source const repoParser = dependency(string()); // Create a derived parser const refParser = repoParser.derive({ metavar: "REF", factory: (repoPath) => { const refs = getRefsFromRepo(repoPath); return choice(refs); }, defaultValue: () => ".", }); const parser = object({ repo: option("--repo", repoParser, { description: message`Path to the repository`, }), ref: option("--ref", refParser, { description: message`Git reference`, }), });
derived parsers that use its value.The factory function is where the dependency gets resolved. It receives the
actual value the user provided for --repo and returns a parser that validates
against refs from that specific repository.Under the hood, Optique uses a three-phase parsing strategy:
Parse all options in a first pass, collecting dependency values Call factory functions with the collected values to create concrete parsers Re-parse derived options using those dynamically created parsersThis means both validation and completion work correctly—if the user has
Repository-aware completion with @optique/git
already typed --repo /some/path, the --ref completion will show refs from
that path.The @optique/git package provides async value parsers that read from Git
import { command, dependency, message, object, option, string, } from "@optique/core"; import { gitBranch } from "@optique/git"; const repoParser = dependency(string()); const branchParser = repoParser.deriveAsync({ metavar: "BRANCH", factory: (repoPath) => gitBranch({ dir: repoPath }), defaultValue: () => ".", }); const checkout = command( "checkout", object({ repo: option("--repo", repoParser, { description: message`Path to the repository`, }), branch: option("--branch", branchParser, { description: message`Branch to checkout`, }), }), );
repositories. Combined with the dependency system, you can build CLIs with
repository-aware completion:Now when you type my-cli checkout --repo /path/to/project --branch <TAB>, the
Multiple dependencies
completion will show branches from /path/to/project. The defaultValue of
"." means that if --repo isn't specified, it falls back to the current
directory.Sometimes a parser needs values from multiple options. The deriveFrom()
import { choice, dependency, deriveFrom, message, object, option, } from "@optique/core"; function getAvailableServices(env: string, region: string): string[] { return [`${env}-api-${region}`, `${env}-web-${region}`]; } const envParser = dependency(choice(["dev", "staging", "prod"] as const)); const regionParser = dependency(choice(["us-east", "eu-west"] as const)); const serviceParser = deriveFrom({ dependencies: [envParser, regionParser] as const, metavar: "SERVICE", factory: (env, region) => { const services = getAvailableServices(env, region); return choice(services); }, defaultValues: () => ["dev", "us-east"] as const, }); const parser = object({ env: option("--env", envParser, { description: message`Deployment environment`, }), region: option("--region", regionParser, { description: message`Cloud region`, }), service: option("--service", serviceParser, { description: message`Service to deploy`, }), });
function handles this:The factory receives values in the same order as the dependency array. If
Async support
some dependencies aren't provided, Optique uses the defaultValues.Real-world dependency resolution often involves I/O—reading from Git
import { dependency, string } from "@optique/core"; import { gitBranch } from "@optique/git"; const repoParser = dependency(string()); const branchParser = repoParser.deriveAsync({ metavar: "BRANCH", factory: (repoPath) => gitBranch({ dir: repoPath }), defaultValue: () => ".", });
repositories, querying APIs, accessing databases. Optique provides async
variants for these cases:The @optique/git package uses isomorphic-git under the hood, so
gitBranch(), gitTag(), and gitRef() all work in both Node.js and Deno.There's also deriveSync() for when you need to be explicit about synchronous
Wrapping up
behavior, and deriveFromAsync() for multiple async dependencies.The dependency system lets you build CLIs where options are aware of each
other—not just for validation, but for shell completion too. You get type
safety throughout: TypeScript knows the relationship between your dependency
sources and derived parsers, and invalid combinations are caught at compile
time.This is particularly useful for tools that interact with external systems where
the set of valid values isn't known until runtime. Git repositories, cloud
providers, databases, container registries—anywhere the completion choices
depend on context the user has already provided.This feature will be available in Optique 0.10.0. To try the pre-release:
deno add jsr:@optique/core@0.10.0-dev.311Or with npm:
npm install @optique/core@0.10.0-dev.311See the documentation for more details.
Post suggeriti
-
RS RERUN—RS199
Watching Ignoring Scheduled Pinned Locked Moved Uncategorized art mastoart comic comics indiecomics webcomic webcomics fantasy
1
0 Votes1 Posts0 Views -
Carex firma.
Watching Ignoring Scheduled Pinned Locked Moved Uncategorized plants roots illustration
1
0 Votes1 Posts4 Views -
I've officially moved servers!
Watching Ignoring Scheduled Pinned Locked Moved Uncategorized mastoart
1
0 Votes1 Posts5 Views -
We have updated our Christmas offerings for 2025 with some new treasures.
Watching Ignoring Scheduled Pinned Locked Moved Uncategorized pottery art christmas mastoart mastodonart
4
0 Votes1 Posts10 Views