{"id":13448440,"url":"https://github.com/erichs/composure","last_synced_at":"2025-04-06T09:08:25.372Z","repository":{"id":3054091,"uuid":"4075859","full_name":"erichs/composure","owner":"erichs","description":"Don't fear the Unix chainsaw","archived":false,"fork":false,"pushed_at":"2022-11-17T08:45:48.000Z","size":230,"stargazers_count":334,"open_issues_count":2,"forks_count":29,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-03-30T07:12:04.668Z","etag":null,"topics":["bash","metadata","shell","versioning","zsh"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"vpulim/node-soap","license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/erichs.png","metadata":{"files":{"readme":"README.md","changelog":"History.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-04-19T14:05:34.000Z","updated_at":"2025-03-29T19:37:23.000Z","dependencies_parsed_at":"2023-01-11T16:14:06.054Z","dependency_job_id":null,"html_url":"https://github.com/erichs/composure","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erichs%2Fcomposure","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erichs%2Fcomposure/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erichs%2Fcomposure/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/erichs%2Fcomposure/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/erichs","download_url":"https://codeload.github.com/erichs/composure/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247457802,"owners_count":20941906,"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":["bash","metadata","shell","versioning","zsh"],"created_at":"2024-07-31T05:01:45.658Z","updated_at":"2025-04-06T09:08:25.350Z","avatar_url":"https://github.com/erichs.png","language":"Shell","readme":"\n     e88~~\\  e88~-_  888-~88e-~88e 888-~88e   e88~-_   d88~\\ 888  888 888-~\\  e88~~8e\n    d888    d888   i 888  888  888 888  888b d888   i C888   888  888 888    d888  88b\n    8888    8888   | 888  888  888 888  8888 8888   |  Y88b  888  888 888    8888__888\n    Y888    Y888   ' 888  888  888 888  888P Y888   '   888D 888  888 888    Y888    ,\n     \"88__/  \"88_-~  888  888  888 888-_88\"   \"88_-~  \\_88P  \"88_-888 888     \"88___/\n                                   888\n\n    # Composure: don't fear the Unix chainsaw\n\nThese light-hearted functions make programming the shell easier and\nmore intuitive:\n\n* Transition organically from command, to function, to script\n* Use an unobtrusive help system with arbitrary shell metadata\n* Automatically version and store your shell functions with Git\n\nstatic analysis and automated tests: [![Build Status](https://travis-ci.org/erichs/composure.png?branch=master)](https://travis-ci.org/erichs/composure)\n\n## Demo!\n\n[Composing a simple network monitoring script](http://asciinema.org/a/476) (4 minutes)\n\n## Compatibility\n\nComposure is POSIX-compliant, and is known to work on ksh93, zsh, and\nbash, on osx and linux.\n\nPlease feel free to open an issue if you have any difficulties on your system.\n\n## Installing\n\nClone this repo, into a directory of your choice and source it from your shell's\nprofile or rc file.\n\nOn Bash:\n\n```bash\n    cd /your/favorite/directory\n    git clone https://github.com/erichs/composure.git\n    cd composure\n    echo \"source $(pwd)/composure.sh\" \u003e\u003e ~/.bashrc   # or, ~/.bash_profile on osx\n```\n\nNote for users with versions prior to 1.4.0: Previous installation methods will work, but cloning the repo is now recommended, as it makes the `glossary` and `reference` commands 100x faster.\n\n## Craft - Draft - Revise - Write\n\n```mermaid\njourney\n    title Typical Usage\n    section Craft\n      Create Useful Shell Command: 1: Shell\n    section Draft\n      Give it a name with 'draft': 2: Editor, Git\n      Use your new shiny function: 3: Shell\n    section Revise\n      Edit/maintain your function with 'revise': 4: Editor, Git\n    section Write\n      Persist to shell scripts with 'write': 5: Shell\n      Profit $$$: 6: You\n```\n\n### Crafting the command line\n\n[REPL environments](http://repl.it) are great for trying out programming ideas\nand crafting snippets of working code, aren't they? Composure helps you make\nbetter use of the REPL environment constantly at your fingertips: the shell.\n\nMany Unix users I know like to iteratively build up complex commands by trying\nsomething out, hitting the up arrow and perhaps adding a filter with a pipe:\n\n```bash\n  $ cat servers.txt\n  bashful: up\n  doc: down\n\n  up-arrow\n\n  $ cat servers.txt | grep down\n  doc: down\n\n  up-arrow\n\n  $ cat servers.txt | grep down | mail -s \"down server(s)\" admin@here.com\n```\n\nComposure helps by letting you quickly draft simple shell functions, breaking down\nyour long pipe filters and complex commands into readable and reusable chunks.\n\n### Draft first, ask questions later\n\nOnce you've crafted your gem of a command, don't throw it away! Use 'draft ()'\nand give it a [good name](http://martinfowler.com/bliki/TwoHardThings.html).\nThis stores your last command as a function you can reuse later. Think of it\nlike a rough draft.\n\n```bash\n  $ cat servers.txt\n  bashful: up\n  doc: down\n\n  up-arrow\n\n  $ cat servers.txt | grep down\n  doc: down\n\n  $ draft finddown\n\n  $ finddown | mail -s \"down server(s)\" admin@here.com\n```\n\n### Revise, revise, revise!\n\nNow that you've got a minimal shell function, you may want to make it better\nthrough refactoring and revision. Use the 'revise ()' command to revise your\nshell function in your favorite editor.\n\n * generalize functions with input parameters\n * add or remove functionality\n * add supporting metadata for documentation\n\n```bash\n  $ revise finddown\n  finddown ()\n  {\n      about finds servers marked 'down' in text file\n      group admin\n      cat $1 | grep down\n  }\n\n  $ finddown servers.txt\n  doc: down\n```\n\n### Get it in Writing\n\nWhen it is time to put your function or functions to use in a shell script, just call write:\n\n```bash\n  $ write finddown \u003e finddown.sh\n```\n\nEdit the main() function, chmod +x, and you're ready to go!\n\n## Arbitrary shell metadata!\n\nComposure uses a simple system of dynamic keywords that allow you to add\nmetadata to your functions. Just call 'cite ()' to initialize your new\nkeyword(s), and use them freely in your functions:\n\n```bash\n  foo()\n  {\n      cite about\n      about perform mad script-foo\n      echo 'foo'\n  }\n```\n\nRetrieve your metadata later by calling 'metafor ()':\n\n```bash\n  typeset -f foo | metafor about  # displays:\n  perform mad script-foo\n```\n\nBy default, composure knows the keywords: about, param, group, author, and example.\n\nThese default keywords are used by the help system:\n\n## Intuitive help system\n\nThe 'glossary ()' function will automatically summarize all functions with\n'about' metadata. If called with a 'group' name as a parameter, it will\nsummarize functions belonging to that group.\n\nTo display apidoc-style help for a function, use 'reference ()'.\n\n```bash\n  $ glossary   # displays:\n  cite                creates a new meta keyword for use in your functions\n  draft               wraps last command into a new function\n  finddown            finds servers marked 'down' in text file\n  foo                 perform mad script-foo\n  glossary            displays help summary for all functions, or summary for a group of functions\n  metafor             prints function metadata associated with keyword\n  reference           displays apidoc help for a specific function\n  revise              loads function into editor for revision\n  write               writes one or more composed function definitions to stdout\n\n  meanwhile\n\n  $ glossary admin   # displays:\n  finddown            finds servers marked 'down' in text file\n\n  and\n\n  $ reference draft  # displays:\n  draft               wraps last command into a new function\n  parameters:\n                      1: name to give function\n  examples:\n                      $ ls\n                      $ draft list\n                      $ list\n```\n\n## Git integration\n\nIf you already use git, installing composure will initialize a ~/.local/composure\nrepository, and store and version your functions there. Just use 'draft ()' and\n'revise ()', they automatically version for you.\n\nComposure supports the [XDG Base Directory](http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html)\nspecification, and will respect your local XDG_DATA_HOME environment variable.\n\nWhy do this?\n\n * the latest version of any function you've composed may always be sourced from\n   your composure repo\n * never throw away code--keep your one-off functions in your composure 'junk\n   drawer', and grep through it later for long-forgotten gems\n * every version of every function you write is always\n   available to you via basic git commands\n\n## Persistent access\n\nDraft or revise a function, and the latest version is automatically sourced into your current shell environment. By default, composure automatically sources all of your composed functions when you source the composure.sh script. If you are concerned about shell startup time, have many hundreds of versioned shell functions, or otherwise want to control which functions are loaded from your composure repository, you may disable the default behavior by adding the following line to your shell's startup script:\n\n```shell\nexport LOAD_COMPOSED_FUNCTIONS=0\n```\n\n# Credits\n\nComposure grew out of ideas taken from from Gary Bernhardt's hilarious talk [The Unix\nChainsaw](http://www.confreaks.com/videos/615-cascadiaruby2011-the-unix-chainsaw) (31 minutes),\nwhich refers to the Elements of Programming described in MIT's [SICP\ntext](http://mitpress.mit.edu/sicp/full-text/book/book.html):\n\n * primitive expressions\n * means of combination\n * means of abstraction\n\n## Known Issues\n\n'glossary ()' and 'reference ()' do not support nested functions with metadata.\n\n`revise` works well if your editor is terminal-based, like Emacs or Vim. If you use a windowed editor like Atom, VSCode, or Sublime, you will need to check to see if your editor supports a flag argument that allows it to wait for the files to be closed before returning. If this is supported, you can create a small script to launch your editor in this mode, and specify that script path in your `EDITOR` var. See https://github.com/erichs/composure/issues/10.\n","funding_links":[],"categories":["Shell","Shell Script Development"],"sub_categories":["Directory Navigation"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ferichs%2Fcomposure","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ferichs%2Fcomposure","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ferichs%2Fcomposure/lists"}