{"id":15748420,"url":"https://github.com/binaryphile/dctk","last_synced_at":"2025-03-31T06:44:54.918Z","repository":{"id":143324939,"uuid":"74403812","full_name":"binaryphile/dctk","owner":"binaryphile","description":"a trapper-keeper way to organize programs","archived":false,"fork":false,"pushed_at":"2017-12-25T20:57:27.000Z","size":99,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-06T11:32:56.714Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/binaryphile.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-11-21T20:39:07.000Z","updated_at":"2016-12-27T14:13:05.000Z","dependencies_parsed_at":"2023-05-14T21:30:39.015Z","dependency_job_id":null,"html_url":"https://github.com/binaryphile/dctk","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binaryphile%2Fdctk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binaryphile%2Fdctk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binaryphile%2Fdctk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/binaryphile%2Fdctk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/binaryphile","download_url":"https://codeload.github.com/binaryphile/dctk/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246429447,"owners_count":20775805,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-04T05:41:44.184Z","updated_at":"2025-03-31T06:44:54.892Z","avatar_url":"https://github.com/binaryphile.png","language":"Shell","readme":"dctk: organize your programs with *[Dawson's Creek Trapper Keeper Ultra Keeper Futura S 2000]*\n==============================================================================================\n\ndctk helps you set up your own command or commands, which use separate\nscripts as subcommands. Such subcommands work much like git's or rbenv's\nsubcommands.\n\nSubcommands are scripts or programs, independent of one another and\ndealing with individual concerns.\n\nThink of it as a way to organize a large amount of functionality into a\nsingle command, like pages in a trapper-keeper, to keep the joke going.\n\nexamples\n========\n\nHere are some quick examples in the model of rbenv, if rbenv were\nimplemented as a trapper-keeper:\n\n    $ rbenv                    # prints out usage and lists available subcommands\n    $ rbenv versions           # runs the \"versions\" subcommand\n    $ rbenv shell 1.9.3-p194   # runs the \"shell\" subcommand, passing \"1.9.3-p194\" as an argument\n\nEach subcommand maps to a separate, standalone executable file.\n\ndctk operates with the following basic tree structure (all are\ndirectories):\n\n    .\n    ├── bin               # your command's link to the dctk executable\n    ├─┬ dctk              # built-in functionality\n    │ └── …\n    ├── completions       # autocompletion for your command\n    ├── [command]         # your command's subcommands\n    └── …\n\ncreating your first command\n===========================\n\nHere's an example of adding a new subcommand. Let's say your\ntrapper-keeper is named \"rush\". Run:\n\n    touch rush/who\n    chmod +x rush/who\n\nEdit `rush/who` with the following:\n\n``` bash\n#!/usr/bin/env bash\n\nwho\n```\n\nNow you can run `rush who`:\n\n    $ rush who\n    qrush     console  Sep 14 17:15\n\nThat's it. You now have a working subcommand.\n\nYou can add autocompletion support and help documentation as well, by\nadding a little bit more to your script, as you'll see.\n\ndctk the project versus the command\n===================================\n\ndctk, the project, is this repo and the code of which it is comprised.\n\nWhile it is invoked using the command `dctk` at the outset, the `dctk`\ncommand is replaced with your own after your customize it to your own\nneeds. `dctk` is just a link in `bin`, a link which will ultimately be\nrenamed to your command's name.\n\nThis readme refers to the project and how it works as dctk, even though\nthere won't be a `dctk` command after you run the `prepare` script to\ncustomize it. Your project will contain dctk's bones but will add the\nfunctionality that makes it your own command.\n\nprerequisites\n=============\n\ndctk requires the [kaizen] bash library.\n\nClone that repo and either add its `lib` to your PATH or put\n`lib/kzn.bash` somewhere already on your PATH.\n\ninstallation\n============\n\nFirst clone this repository to your own command's name:\n\n    $ git clone --depth=1 git://github.com/binaryphile/dctk [your command name]\n\nThen run the `prepare` script while in this directory:\n\n    $ cd [command]\n    $ ./prepare [command]\n\nThird, add the following to your shell's startup script (.bash\\_profile\nor .zshrc, for example):\n\n    eval \"$(\"$HOME\"/[path to your dctk]/bin/[command] init -)\"\n\nFinally, you may decide to get rid of the `.git` folder and start your\nown repository.\n\nOnce `prepare`d, dctk becomes the new command is invoked like so:\n\n    $ [command] [subcommand] [(args)]\n\nthe dctk command\n================\n\nAfter preparation, your command in `bin` is a link to the dctk script in\n`dctk/bin/dctk`. You can examine the file there to see the guts of dctk\nin action.\n\ndctk determines your command's name from how it was invoked on the\ncommand-line, so the fact that its filename doesn't match the command is\nnot important.\n\nFrom here on out, when this document refers to the `dctk` command, it\nmeans your command instead, once you've prepared the project, so just\nvisualize that command's name wherever it says `dctk`.\n\nwhat's in your trapper-keeper\n=============================\n\nYour trapper-keeper comes with a few subcommands already built-in:\n\n-   `dctk commands` - print available subcommands\n\n-   `dctk completions` - provide command completion details for use by\n    shell autocompletion\n\n-   `dctk help` - parse and display subcommand help, if provided in the\n    script\n\n-   `dctk init` - hook completions into the shell, usually when invoked\n    from a shell startup file (e.g. `.bash_profile`)\n\nsubcommands\n===========\n\nSubcommands live in the directory named for your command and are simply\nnamed for the subcommand, e.g. `rbenv/versions`. For this reason you\ncan't make a command with the same name as the existing directories,\n`bin`, `dctk`, `completions` or `shpec`. Anything else is fair game.\n\nSubcommands don't have to be written in bash. They can be any\nexecutable, scripted or compiled. Even symlinks work.\n\nSubcommands can provide documentation in comments, automatically made\navailable through the `dctk` and `dctk help [subcommand]` commands.\n\nSubcommands can also provide shell autocompletion by implementing a\nwell-known flag (`--complete`). dctk handles the details of informing\nthe shell (bash and zsh supported).\n\nself-documenting subcommands\n============================\n\nDocumentation is provided by adding leading comments to your script.\nThis feature is limited to scripts which use \"\\#\" as their comment\ndelimiter.\n\nHere's an example from `rush who`:\n\n``` bash\n#!/usr/bin/env bash\n# Usage: rush who\n# Summary: Check who's logged in\n# Help: This will print out when you run `rush help who`.\n# You can have multiple lines even!\n#\n#    Show off an example indented\n#\n# And maybe start off another one?\n\nwho\n```\n\nNow, when you run `rush`, the \"Summary\" magic comment will now show up:\n\n    usage: rush \u003ccommand\u003e [\u003cargs\u003e]\n\n    Some useful rush commands are:\n       commands               List all rush commands\n       who                    Check who's logged in\n\nAnd running `rush help who` will show the \"Usage\" magic comment, and\nthen the \"Help\" comment block:\n\n    Usage: rush who\n\n    This will print out when you run `rush help who`.\n    You can have multiple lines even!\n\n       Show off an example indented\n\n    And maybe start off another one?\n\nBecause it is free-form, the Help section must be the last of your\nleading comments in the script.\n\nautocompletion\n==============\n\ndctk provides autocompletion at two levels:\n\n1.  autocompletion of subcommand names (what subcommands are available?)\n\n2.  (optional) autocompletion of subcommand arguments (what arguments\n    does this subcommand take?)\n\nThe second requires that you add another leading comment, like so:\n\n``` bash\n#!/usr/bin/env bash\n# Completions: true\n# Usage: rush who\n```\n\nYour script must also parse the flag `--complete`. For example:\n\n``` bash\n#!/usr/bin/env bash\n\n# completions: true\nif [[ $1 == \"--complete\" ]]; then\n  echo \"--path\"\nfi\n\n# etc...\n```\n\nYour subcommand should echo the list of valid completions and exit when\nreceiving the `--complete` flag instead of normal operation. dctk feeds\nthis output to your shell's autocompletion handler for you.\n\nmultiple commands\n=================\n\nWhen you saw the directory tree earlier, it was for a single command.\nHowever you can have multiple commands as well, independent of each\nother.\n\n    .\n    ├── bin               # your commands' links to the dctk executable\n    ├── completions       # your commands' links to the completions script\n    ├── …\n    ├── [command]         # one command's subcommands\n    ├── [another command] # you can have more than one\n    └── …\n\nEach command exists side-by-side in its own directory. Each has its own\nsubcommands.\n\nAll that is required to become a command is for the directory to exist,\nand for there to be link with the command's name to the dctk executable:\n\n    $ mkdir [command]\n    $ cd bin\n    $ ln -sf ../dctk/bin/dctk [command]\n\nYou should also enable completions for your command with a link:\n\n    $ cd ../completions\n    $ ln -sf ../dctk/completions/dctk.bash [command].bash   # or .zsh, if that's your shell\n\nAdd subcommands to the \\[command\\] directory and you're good to go.\n\nstructured commands\n===================\n\nSo far, you've seen simple commands. Subcommands exist simply as\nexecutables in their command's directory.\n\nHowever, your commands may require more structure. For example, you may\nhave data files which might go in `[command]/share`.\n\nOr you may have a command which is already a project of its own, such as\nan existing [sub] or a repo you'd like to add as a git submodule.\n\n    .\n    ├── …\n    ├─┬ [command]\n    │ ├── bin             # if bin and/or libexec exist, look there instead for subcommands\n    │ ├── libexec         # for example, when importing an existing project or [sub]\n    │ ├── share           # or to separate out supporting files\n    │ └── other           # whatever you like\n    └── …\n\nIf dctk sees a `[command]/bin` and/or `[command]/libexec` directory, it\nwill treat the command as structured. A structured command finds its\nsubcommands in the `bin` and `libexec` subdirectories instead of the\nmain `[command]` directory (with `bin` taking priority in conflicts).\n\nIf you ever need to reference files in other subdirectories of your\nstructured command, say to access a file in the `[command]/share`\ndirectory, dctk provides the environment variable `_[COMMAND]_ROOT`. For\nexample, if your command is named \"rush\", then the variable is\n`_RUSH_ROOT`, which expands to `[path to dctk]/rush`. That would make\nthe share folder `$_RUSH_ROOT/share`.\n\nwhy \"trapper-keeper\"?\n=====================\n\ndctk is meant to make it easy to assimilate any kind of technology into\nyour trapper-keeper as a subcommand, much like *Dawson's Creek Trapper\nKeeper Ultra Keeper Futura S 2000* assimilated all of Cartman's\nbelongings (as well as Cartman himself). His trapper-keeper ultimately\nbecame sentient and took over the world. Hopefully yours will be less\nambitious, while still as powerful.\n\nisn't dctk just a rip-off of [sub]?\n===================================\n\ndctk is inspired by sub but shares almost no code, being a ground-up\nrewrite. It also sports numerous additional features:\n\n-   multiple top-level commands in one trapper-keeper\n\n-   structured commands\n\nFuture:\n\n-   hierarchical subcommands by nesting directories\n\n-   functions as subcommands\n\n-   [docopt] support\n\nLicense\n=======\n\nApache 2.0. See `LICENSE.md`.\n\n  [Dawson's Creek Trapper Keeper Ultra Keeper Futura S 2000]: https://en.wikipedia.org/wiki/Trapper_Keeper_(South_Park)\n  [kaizen]: https://github.com/binaryphile/kaizen\n  [sub]: https://github.com/basecamp/sub\n  [docopt]: http://docopt.org/\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbinaryphile%2Fdctk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbinaryphile%2Fdctk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbinaryphile%2Fdctk/lists"}