{"id":19051965,"url":"https://github.com/benknoble/plink","last_synced_at":"2025-08-12T18:05:42.097Z","repository":{"id":70217125,"uuid":"196785658","full_name":"benknoble/plink","owner":"benknoble","description":"The DSL for Dotfiles","archived":false,"fork":false,"pushed_at":"2020-02-07T04:31:29.000Z","size":40,"stargazers_count":1,"open_issues_count":2,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-22T00:41:55.363Z","etag":null,"topics":["dotfiles","dotfiles-automation","dotfiles-install","dotfiles-manager","make","makefile-generation","perl","plink"],"latest_commit_sha":null,"homepage":"","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/benknoble.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2019-07-14T02:35:03.000Z","updated_at":"2020-11-14T11:14:29.000Z","dependencies_parsed_at":"2023-03-11T08:19:02.648Z","dependency_job_id":null,"html_url":"https://github.com/benknoble/plink","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/benknoble/plink","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benknoble%2Fplink","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benknoble%2Fplink/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benknoble%2Fplink/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benknoble%2Fplink/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/benknoble","download_url":"https://codeload.github.com/benknoble/plink/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benknoble%2Fplink/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270109371,"owners_count":24528789,"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","status":"online","status_checked_at":"2025-08-12T02:00:09.011Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["dotfiles","dotfiles-automation","dotfiles-install","dotfiles-manager","make","makefile-generation","perl","plink"],"created_at":"2024-11-08T23:20:19.245Z","updated_at":"2025-08-12T18:05:42.020Z","avatar_url":"https://github.com/benknoble.png","language":"Perl","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NAME\n\nPlink, plink - the DSL-for-dotfiles program\n\n# SYNOPSIS\n\n    # command-line usage\n    # head -n 1 dotfiles.plink\n    #! /usr/bin/env /path/to/Plink.pm\n    # ./dotfiles.plink\n    # make\n\n[![This project is considered stable](https://img.shields.io/badge/status-stable-success.svg)](https://benknoble.github.io/status/stable/)\n\n# DESCRIPTION\n\nThe **Plink** module provides an implementation of the Plink language, a DSL\nbuilt to describe dotfiles via symlinks. The language is a strict superset of\nmake(1); implementations produce (POSIX) makefiles for use. It is important to\nnote that Plink only guarantees that generated code is POSIX-compatible.\nUser-written code may use GNU make or other non-portable features. What follows\nis the canonical specification of the Plink language.\n\n## Plink Specification\n\nPlink is superset of POSIX make. It defines four (4) new syntaxes with semantic\nmeaning.\n\nPlink also defines a header and footer.\n\nA conforming implementation transforms the input file (or STDIN) as specified by\nthe syntaxes. All lines not participating in one of these syntaxes, in addition\nto `#` comments, are copied verbatim (this includes blank lines). The output is\nwritten to a file named by the environment variable `PLINK_OUTPUT`, or\n`Makefile` if unset.\n\nSee `t/test.plink` for an example Plink file, and `t/expected.mk` for its\noutput.\n\n### Square Brackets `[ prerequisites ]`\n\nAny line like\n\n    target names [ prerequisites ] ...\n\nwill be transformed to\n\n    target names: $MAKEFILE prerequisites ...\n\n`$MAKEFILE` denotes the name of the generated filename.  The spaces around\n`[]` are not _required_, but often recommended. `...` may make use of any the\nbang-syntaxes.\n\n### Bang and Double-bang `!` `!!`\n\nLines like\n\n    target ! commands\n\nwill be transformed to\n\n    target:\n    \u003cTAB\u003ecommands\n\nThe list `commands` lasts to the end of the line. `commands` will be indented\nby one tab, as make requires.\n\nSimilarly, lines like\n\n    target !!\n    commands\n    on more lines\n    !!\n\nbecome\n\n    target:\n    \u003cTAB\u003ecommands\n    \u003cTAB\u003eon more lines\n\nThe list `commands` lasts until the line containing _exactly_ `!!`. Commands\nwill be tab-indented.\n\n### Symlink (Fat-arrow) `\u003c=`\n\nThe meat of the DSL. Lines like\n\n    link_in_home \u003c= dotfile_under_$(LINKS)\n\nBecome part of a mapping. The output creates dependencies of the form\n\n    $(HOME)/link_in_home: $(LINKS)dotfile_under_$(LINKS)\n\nfor each fat-arrow, and also gives each the recipe\n\n    if test -e $@ || test -L $@ ; then rm -rf $@ ; fi\n    ln -s $$(python -c \"from os.path import *; print(relpath('$?', start=dirname('$@')))\") $@\n    @echo $@ '-\u003e' $$(python -c \"from os.path import *; print(relpath('$?', start=dirname('$@')))\")\n\nwhich creates the link. Finally, a target named `symlink` is provided which\ndepends on all the `link_in_home`s provided: it is considered the public API\nfor any make target that wishes to depend on symlink-generation.\n\nDotfiles are files under the make macro `$(LINKS)`. Due to the generation rule,\nif `$(LINKS)` is not set, the current directory is used. This can be useful to\nput all dotfiles under a directory named, e.g., `dots`. Then you want to\ninclude a line in your Plink file like\n\n    LINKS = dots/\n\n(note the trailing slash).\n\nThe use of the macro `SYMLINKS` is considered a Plink implementation detail and\nis subject to change; users who set `SYMLINKS` or depend on it's effects are\ninvoking undefined behavior.\n\n### Header\n\nThe Plink header consists of\n\n    SHELL = /bin/sh\n    .SUFFIXES:\n\n### Footer\n\nThe Plink footer consists of the symlink target implementation and the\nfollowing:\n\n    MAKEFILE: INPUT\n    \u003cTAB\u003e$$(python -c \"from os.path import *; print(abspath('$?'))\")\n\n`MAKEFILE` refers to the generated output, and `INPUT` to the Plink file used\nas input.\n\n## Normal Usage\n\nSince Plink is a superset of make, your current makefile is valid under Plink\nand will be transformed to exactly itself. This means the quickest way to get\nstarted is to move your makefile to a `.plink`-file, and edit the shebang to\npoint to `#! /usr/bin/env /path/to/Plink.pm`. If you don't have env(1), the\npath to perl(1) should work.\n\nOpt-in to Plink features by re-writing portions of your new Plink file to\ntake advantage of Plink.\n\nThen, run your Plink file to generate a Makefile. Use make(1) to run your\ntargets! (Be sure to `chmod u+x ./some.plink`.). Note that all Plink-generated\ntargets depend on the generated Makefile, which depends on the Plink file\nused to generate it. This means that users taking full advantage of Plink should\nonly need to `make` when they edit their Plink file.\n\n## Advanced: Bypassing Plink\n\nOmit Plink-level syntax to guarantee that no processing is done on your code.\nThe most common use of this is to disable Plink's insistence that everything\ndepends on the output file; do not specify pre-requisites in `[ square brackets\n]` to ignore this.\n\n# METHODS\n\n_plink_ _$infname_, _$outfname_\n\nImplements the Plink specification, transforming the file named `infname` to\n`outfname`. Handles for STDIN and STDOUT are accepted, though STDIN has the\nside-effect that the Makefile rules now depend on the literal file `STDIN`.\nSimilarly, STDOUT breaks the rule to make the generated Makefile.\n\n# OPTIONS\n\n- _Plink\\_file_\n\n    The Plink file from which to generate the output.\n\n# DIAGNOSTICS\n\nEnable diagnostics by putting `use diagnostics;` at the top of the module.\n\n# EXAMPLES\n\nSee the `t` directory.\n\n# ENVIRONMENT\n\n- PLINK\\_OUTPUT\n\n    Used to determine where to write the output. Defaults to `Makefile`.\n\n# FILES\n\nSee [\"#ENVIRONMENT\"](#environment).\n\n# CAVEATS\n\nSee the [Specification](#plink-specification) for caveats on symlink\nimplementations.\n\n# BUGS\n\nGenerated Makefiles may choke on paths with spaces. Avoid those for now.\n\n# AUTHOR\n\nD. Ben Knoble \u0026lt;ben.knoble+plink@gmail.com\u003e\n\n# COPYRIGHT AND LICENSE\n\nCopyright 2019 D. Ben Knoble\n\nSee `LICENSE`.\n\n# SEE ALSO\n\nmake(1), [https://github.com/benknoble/Dotfiles](https://github.com/benknoble/Dotfiles), [https://github.com/benknoble/vim-plink](https://github.com/benknoble/vim-plink)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenknoble%2Fplink","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbenknoble%2Fplink","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenknoble%2Fplink/lists"}