]> git.wincent.com - wincent.git/commitdiff
docs: remove references to Ansible
authorGreg Hurrell <greg@hurrell.net>
Sat, 2 May 2020 17:13:41 +0000 (19:13 +0200)
committerGreg Hurrell <greg@hurrell.net>
Sat, 2 May 2020 17:13:41 +0000 (19:13 +0200)
.github/ISSUE_TEMPLATE.md
.github/PULL_REQUEST_TEMPLATE.md
.prettierignore
README.md
aspects/iterm/README.md
aspects/launchd/README.md
aspects/vim/index.ts
fig/README.md [new file with mode: 0644]
package.json

index 65a5881227c645a81910603dab0ff9c568e4d8fd..7df03988e3fa3a1418d74fbe3d8c8387ef87b98a 100644 (file)
@@ -1,17 +1,15 @@
 ## Expected Behavior
 
-
 ## Actual Behavior
 
-
 ## Steps to Reproduce the Problem
 
-1.
-2.
-3.
+1. ...
+2. ...
+3. ...
 
 ## Specifications
 
-- Version:
-- Platform:
-- Subsystem:
+-   Version:
+-   Platform:
+-   Subsystem:
index b89b6ff4ce8707425a161b4e1b75c6370606e924..51e1e7e8fc86215508488b9df66716c29dfac84d 100644 (file)
@@ -2,6 +2,5 @@ Fixes #
 
 ## Proposed Changes
 
--
--
--
+-   ...
+-   ...
index 56598537b5c2efc258db58a248e2ab0ed56656da..2ab0a1e979c7dcf4e61bc07e72c0764c24e090ad 100644 (file)
@@ -1,3 +1,9 @@
+/aspects/dotfiles/files/.config/kitty/base16-kitty
+/aspects/dotfiles/files/.zsh/base16-shell
+/aspects/dotfiles/files/.zsh/skim
+/aspects/dotfiles/files/.zsh/zsh-autosuggestions
+/aspects/dotfiles/files/.zsh/zsh-history-substring-search
+/aspects/dotfiles/files/.zsh/zsh-syntax-highlighting
 /aspects/vim/files/.vim
 /fig/types
 /lib
index c69128abe7f49bbdcc5942ce52b5775b769016d0..afd9c17975cd9fe446bdfdbadf5baca57bd70676 100644 (file)
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
 ![](https://raw.githubusercontent.com/wincent/wincent/media/screenshot.png)
 
 -   Target platforms: macOS and Red Hat-like Linuxes (eg. CentOS).
--   Set-up method: ~~Beautiful and intricate snowflake~~ incredibly over-engineered [Ansible](https://www.ansible.com/) orchestration.
+-   Set-up method: ~~Beautiful and intricate snowflake~~ an incredibly over-engineered custom configuration framework called [Fig](./fig/README.md).
 -   Visible in the screenshot:
     -   [default-dark Base16](http://chriskempson.com/projects/base16/) color scheme (see [screenshots of other colorschemes](https://github.com/wincent/wincent/blob/media/colorschemes/README.md)).
     -   [Adobe Source Code Pro](https://github.com/adobe-fonts/source-code-pro) (Light) font.
@@ -32,7 +32,7 @@
 
 ### Homebrew
 
-On macOS, [the `homebrew` role](https://github.com/wincent/wincent/tree/master/roles/homebrew) installs [a bunch of useful software](https://github.com/wincent/wincent/blob/master/roles/homebrew/templates/Brewfile).
+On macOS, [the "homebrew" aspect](https://github.com/wincent/wincent/tree/master/aspects/homebrew) installs [a bunch of useful software](https://github.com/wincent/wincent/blob/master/aspects/homebrew/templates/Brewfile.erb).
 
 ### Keyboard customization
 
@@ -134,29 +134,40 @@ git clone --recursive https://github.com/wincent/wincent.git
 
 ### Install
 
-```sh
-./install-legacy          # Installs everything on the local machine.
-./install-legacy --help   # Info on installing specific roles, force-installing etc.
-./install-legacy dotfiles # Just install dotfiles.
-```
-
-This sets up a local Python environment using the bundled virtualenv, bootstraps Ansible, and then uses Ansible to copy the dotfiles and configure the machine.
-
-Again, if you're behind a firewall, you may need to make use of a proxy during the initial run:
-
-```sh
-env http_proxy=http://fwdproxy:8080 https_proxy=http://fwdproxy:8080 ./install-legacy
-```
-
-As a fallback strategy, in case the `install-legacy` script fails, you can symlink the dotfiles by hand with a command like the following:
+> ⚠️ **WARNING:** There are _lots_ of different things that can be installed or configured (see [the "aspects" directory](./aspects)). Unless you want your machine to be exactly like mine — which is unlikely — you probably don't want to install _everything_. Maybe you don't even want everything in the ["dotfiles"](./aspects/dotfiles) and ["vim"](./aspects/vim) aspects. Please inspect the contents of each aspect before proceeding to install it; you may even be better off just looking at the configuration files and stealing the bits that you find interesting or useful (everything is [in the public domain](./LICENSE.md), unless otherwise indicated).
+
+At the time of writing, these are the aspects, which you can expect to change over time:
+
+-   **automator**: Scripts for use with Automator
+-   **backup**: Backup scripts
+-   **cron**: Sets up cron files
+-   **defaults**: Sets up defaults (ie. preferences) on macOS
+-   **dotfiles**: Creates symlinks in \$HOME to the dotfiles in this repo
+-   **fonts**: Installs Source Code Pro font files
+-   **homebrew**: Installs and updates Homebrew
+-   **iterm**: Dynamic profiles for iTerm
+-   **karabiner**: Configures Karabiner-Elements
+-   **launchd**: Configures launchd
+-   **meta**: Tests the configuration framework
+-   **node**: Installs Node.js
+-   **ruby**: Installs Ruby gems
+-   **shell**: Sets the use shell to zsh
+-   **ssh**: Manages local SSH config
+-   **terminfo**: Sets up terminfo database entries for italics and 256-color support
+-   **vim**: Configures Vim
+
+#### Examples
 
 ```sh
-for DOTFILE in $(find aspects/dotfiles/files -maxdepth 1 -name '.*' | tail -n +2); do
-  ln -sf $PWD/$DOTFILE ~
-done
+./install dotfiles vim      # Just install "dotfiles" and "vim" stuff.
+./install dotfiles          # Just install "dotfiles".
+./install dotfiles --step   # Prompt for confimration at each step.
+./install dotfiles --check  # Do a dry-run, showing what would be changed.
+./install                   # Install everything.
+./install --help            # Info on installing specific rol
 ```
 
-**Note:** The `ln -sf` command will overwrite existing files, but will fail to overwrite existing directories.
+This sets up a local Node environment using [n](https://github.com/tj/n), and then uses [Fig](./fig/README.md) to copy the dotfiles and configure the machine.
 
 **Note:** Given that `~/.gitconfig` is included with these dotfiles, any local modifications or overrides that you apply should be added to `~/.gitconfig.local` instead; for example:
 
@@ -167,65 +178,21 @@ git config --file ~/.gitconfig.local user.email johndoe@example.com
 
 ### Troubleshooting
 
-#### General Ansible troubleshooting
+#### General troubleshooting
 
-Flags passed to `./install-legacy` are propagated to the underlying Ansible invocation, which means that you can do things like:
+There are a few useful `./install` options:
 
 ```sh
 # Run in "check" (dry-run) mode.
-./install-legacy --check
+./install --check
 
-# Show before-and-after delta of changes.
-./install-legacy --diff
-
-# Both of the above together.
-./install-legacy --check --diff
-
-# Show various levels of debug output.
-./install-legacy --verbose
-./install-legacy -vv
-./install-legacy -vvv
-./install-legacy -vvvv
+# Show debugging information during the run.
+./install --debug
 
 # Confirm each task before running it (--step), and begin
-# execution from a specific task (--start-at-task).
-./install-legacy --step --start-at-task='dotfiles | create backup directory'
-```
-
-You can also inspect variables by adding a task that uses the "debug" module in a role:
-
-```yaml
-- name: buggy task
-  stat: path="~/{{ item }}"
-  register: stat_result
-  with_items: '{{ dotfile_files + dotfile_templates }}'
-
-- name: debugging bad stat info
-  debug:
-      var: stat_result
-```
-
-Note that for convenience, "debug" tasks have already been inserted for all variables that are `register`-ed in the existing roles, with verbosity thresholds of 2, meaning that they will be logged automatically when the install is run using `./install-legacy -vv` or more.
-
-#### pycrypto install fails with "'gmp.h' file not found"
-
-If pycrypto causes the install to fail at:
-
-```sh
-src/_fastmath.c:36:11: fatal error: 'gmp.h' file not found
-```
-
-due to [a missing GMP dependency](http://stackoverflow.com/questions/15375171/pycrypto-install-fatal-error-gmp-h-file-not-found), try:
-
-```sh
-brew install gmp
-env "CFLAGS=-I/usr/local/include -L/usr/local/lib" pip install pycrypto
-```
-
-And then installing again:
-
-```sh
-./install-legacy --force
+# execution from a specific task (--start-at-task) in a
+# specific aspect ("dotfiles").
+./install --step --start='make directories' dotfiles
 ```
 
 #### Broken Unicode in Vim (Linux)
@@ -249,40 +216,6 @@ LANG=en_US.UTF-8
 LC_ALL=en_US.UTF-8
 ```
 
-### How this repo works
-
-0. **2009**: Originally, the repo was just a [collection of files](https://github.com/wincent/wincent/tree/61a7e2a830edb757c59e542039131e671da8b154) with no installation script.
-1. **2011-2015**: I [created a `bootstrap.rb` script](https://github.com/wincent/wincent/commit/e29b2818c487529eb4e7662a23df56445b448fe3) ([final version here](https://github.com/wincent/wincent/blob/94fb4d50243b97cd0c92a5691ac430353a5299a0/bootstrap.rb)) for performing set-up.
-1. **2015**: I [briefly experimented](https://github.com/wincent/wincent/commit/4efdb1f97685bf735b068835adced059cd721096) with using a `Makefile` ([final version here](https://github.com/wincent/wincent/blob/01b37a546b92f60e659a8153067353d58805a009/Makefile)).
-1. **2015-2020**: I [switched to Ansible](https://github.com/wincent/wincent/commit/375f27a6ea6fdd78fcf6614d3af5335da7a9f5ef) (completing the transition in [cd98e9aaab](https://github.com/wincent/wincent/commit/cd98e9aaab82b1983aeab839d4f28260d6e19919)).
-1. **2020-present**: I started [feeling misgivings about the size of the dependency graph](https://github.com/wincent/wincent/issues/82) and in truth I was probably using less than 1% of Ansible's functionality, so moved to the current set-up, which is described below.
-
-The goal was to replace Ansible with some handmade scripts using the smallest dependency graph possible. I original [tried](https://github.com/wincent/wincent/commit/8809a1681cfd8fd02eb40113d2485d7cadc10e4c) out [Deno](https://deno.land/) because that would enable me to use TypeScript with no dependencies outside of Deno itself, however I [gave up on that](https://github.com/wincent/wincent/commit/a213ddf69d3213882808b5c5ff0e000bcd83fe98) when I saw that editor integration was still very nascent. So I went with the following:
-
--   [n](https://github.com/tj/n) ([as a submodule](https://github.com/wincent/wincent/tree/master/vendor)) and some [hand-rolled Bash scripts](https://github.com/wincent/wincent/tree/master/bin) to replace [virtualenv](https://virtualenv.pypa.io/) and friends ([Python](https://www.python.org/), [pip](https://pypi.org/project/pip/)).
--   [Yarn](https://github.com/yarnpkg/yarn/) ([vendored](https://github.com/wincent/wincent/commit/26adf86d4c742390537be4dc1572f93a97bc3e68)) to install [TypeScript](https://www.typescriptlang.org/).
-
-Beyond that, there are no dependencies outside of the [Node.js](https://nodejs.org/en/) standard library. I use [Prettier](https://prettier.io/) to format code, but I invoke it via `npx` which means the [yarn.lock](https://github.com/wincent/wincent/blob/master/yarn.lock) remains basically empty. Ansible itself is replaced by [a set of self-contained TypeScript scripts](https://github.com/wincent/wincent/tree/master/src). Instead of YAML configuration files containing "declarative" configuration peppered with Jinja template snippets containing Python and filters, we just use TypeScript for everything. Instead of [Jinja template files](https://jinja.palletsprojects.com/), we use ERB/JSP-like templates that use embedded JavaScript when necessary.
-
-Because I need a name to refer to this "set of scripts", it's called Fig (a play on "Config"). Overall structure remains similar to Ansible, but I made some changes to better reflect the use case here. While Ansible is made to orchestrate multiple (likely remote) hosts, Fig is for configuring one local machine at a time.
-
-| Ansible                                                                                                                         | Fig                                                                                                             |
-| ------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
-| **Hosts:** Machines to be configured (possibly remote)                                                                          | n/a (always the current, local machine)                                                                         |
-| **Groups:** Collections of hosts, so you can conveniently target multiple hosts without having to address each one individually | **Profiles:** An abstract category indicating the kind of a host (eg. "work" or "personal")                     |
-| **Inventory:** A list of hosts (or groups of hosts) to be managed                                                               | n/a ("project.json" file contains map from hostname to profile to be applied)                                   |
-| **Roles:** Capabilities that a host can have (eg. webserver, file-server etc)                                                   | **Aspects:** Logical groups of functionality to be configured (eg. dotfiles, terminfo etc)                      |
-| **Tasks:** Operations to perform (eg. installing a package, writing a file                                                      | **Tasks:** Same as Ansible.                                                                                     |
-| **Plays:** A mapping between hosts (or groups) and the tasks to be performed on them                                            | n/a (it's just a file containing tasks)                                                                         |
-| **Playbooks:** Lists of plays                                                                                                   | n/a ("project.json" file contains a map from platform to the aspects that should be set up on a given platform) |
-| **Tags:** Keywords that can be applied to tasks and roles, useful for selecting them to be run                                  | n/a (not needed)                                                                                                |
-| **Facts:** (Inferred) attributes of hosts                                                                                       | **Attributes:** Same as Ansible, but with a better name                                                         |
-| **Vars:** (Declared) values that can be assigned to groups, hosts or roles                                                      | **Vars:** Same as Ansible, but belong to profiles and aspects                                                   |
-| **Modules:** Units of code that implement operations (ie. these are what tasks use to actually do the work)                     | **Operations:** Code for performing operations                                                                  |
-| **Templates:** Jinja templates with embedded Python and "filters"                                                               | **Templates:** ERB templates with embedded JavaScript                                                           |
-| **Files:** Raw files that can be copied using modules                                                                           | **Files:** Raw files that can be copied using operations                                                        |
-| **Syntax:** YAML with interpolated Jinja syntax containing Python and variables                                                 | **Syntax:** TypeScript and (plain) JSON                                                                         |
-
 ### License
 
 Unless otherwise noted, the contents of this repo are in the public domain. See the [LICENSE](LICENSE.md) for details.
index 965b594197f1141d5d2f67fcee49c5a5b82e92c6..78103eb0fa4dd6ec8277181321ce4e6bca17dabb 100644 (file)
@@ -2,40 +2,40 @@ iTerm2 has a "[Dynamic Profiles feature](https://www.iterm2.com/documentation-dy
 
 This is nice for version control purposes, but our principal motivation here is to have the ability to apply different configs depending on whether an external monitor is plugged in (because an external 4K display and the internal Retina display on the laptop require different font sizes in order to produce the same physical size on the screen). We [use Hammerspoon](https://github.com/wincent/wincent/tree/master/roles/dotfiles/files/.hammerspoon) to watch for screen layout changes and when they occur, overwrite the symlinks at:
 
-- `$HOME/Library/Application Support/iTerm2/DynamicProfiles/Mutt.json` (this is the profile used for mutt windows).
-- `$HOME/Library/Application Support/iTerm2/DynamicProfiles/Vim.json` (this is the profile used for `vim://` windows).
-- `$HOME/Library/Application Support/iTerm2/DynamicProfiles/Wincent.json` (this is the profile used for other windows).
+-   `$HOME/Library/Application Support/iTerm2/DynamicProfiles/Mutt.json` (this is the profile used for mutt windows).
+-   `$HOME/Library/Application Support/iTerm2/DynamicProfiles/Vim.json` (this is the profile used for `vim://` windows).
+-   `$HOME/Library/Application Support/iTerm2/DynamicProfiles/Wincent.json` (this is the profile used for other windows).
 
 Overwriting the targets that the symlinks point to causes iTerm to read them and pick up the changes. The link targets are all stored in the "Sources" directory here:
 
-- `$HOME/Library/Application Support/iTerm2/Sources/70-Vim-Retina.json` (`vim://` settings for Retina).
-- `$HOME/Library/Application Support/iTerm2/Sources/40-Mutt-Retina.json` (mutt settings for Retina).
-- `$HOME/Library/Application Support/iTerm2/Sources/10-Retina.json` (settings for other Retina windows).
-- `$HOME/Library/Application Support/iTerm2/Sources/70-Vim-4K.json` (`vim://` settings for the 4K display).
-- `$HOME/Library/Application Support/iTerm2/Sources/40-Mutt-4K.json` (mutt settings for the 4K display).
-- `$HOME/Library/Application Support/iTerm2/Sources/10-4K.json` (settings for other windows on the 4K display).
+-   `$HOME/Library/Application Support/iTerm2/Sources/70-Vim-Retina.json` (`vim://` settings for Retina).
+-   `$HOME/Library/Application Support/iTerm2/Sources/40-Mutt-Retina.json` (mutt settings for Retina).
+-   `$HOME/Library/Application Support/iTerm2/Sources/10-Retina.json` (settings for other Retina windows).
+-   `$HOME/Library/Application Support/iTerm2/Sources/70-Vim-4K.json` (`vim://` settings for the 4K display).
+-   `$HOME/Library/Application Support/iTerm2/Sources/40-Mutt-4K.json` (mutt settings for the 4K display).
+-   `$HOME/Library/Application Support/iTerm2/Sources/10-4K.json` (settings for other windows on the 4K display).
 
 But I confess now that the above is a lie. Each of those profiles also has a "parent" profile so that they can inherit common settings and only specify overrides.
 
-- `10-4K.json` and `10-Retina.json`, for example, inherit from a file called `00-Base.json`.
-- `70-Vim-4K.json` and `70-Vim-Retina.json`, inherit from `60-Vim-Base.json`.
-- `40-Mutt-4K.json` and `40-Mutt-Retina.json`, inherit from `30-Mutt-Base.json`.
-- `30-Mutt-Base.json` itself inherits from `00-Base.json`.
+-   `10-4K.json` and `10-Retina.json`, for example, inherit from a file called `00-Base.json`.
+-   `70-Vim-4K.json` and `70-Vim-Retina.json`, inherit from `60-Vim-Base.json`.
+-   `40-Mutt-4K.json` and `40-Mutt-Retina.json`, inherit from `30-Mutt-Base.json`.
+-   `30-Mutt-Base.json` itself inherits from `00-Base.json`.
 
 The number prefixes are there because dynamic profiles are loaded in alphabetical order. We must make sure that parent profiles are loaded before their children, so the global ordering is thus:
 
-- `00-Base.json`
-- `10-4K.json`
-- `10-Retina.json`
-- `30-Mutt-Base.json`
-- `40-Mutt-4K.json`
-- `40-Mutt-Retina.json`
-- `60-Vim-Base.json`
-- `70-Vim-4K.json`
-- `70-Vim-Retina.json`
-- `Mutt.json`
-- `Vim.json`
-- `Wincent.json`
+-   `00-Base.json`
+-   `10-4K.json`
+-   `10-Retina.json`
+-   `30-Mutt-Base.json`
+-   `40-Mutt-4K.json`
+-   `40-Mutt-Retina.json`
+-   `60-Vim-Base.json`
+-   `70-Vim-4K.json`
+-   `70-Vim-Retina.json`
+-   `Mutt.json`
+-   `Vim.json`
+-   `Wincent.json`
 
 The "base" parent profiles never (or rarely) actually change, and we never need to swap one of them for another by changing a symlink target, so those ones live in this dotfiles repo and we have symlinks from `$HOME/Library/Application Support/iTerm2/DynamicProfiles` directly to them in `roles/iterm/files/DynamicProfiles`.
 
@@ -43,26 +43,26 @@ The "Mutt.json" and "Wincent.json" profiles are just symlinks to the "real" prof
 
 ## Summary
 
-- Just symlinks; changing what these points at causes iTerm2 to switch to a different profile:
-  - `Mutt.json`
-  - `Vim.json`
-  - `Wincent.json`
-- Actual profiles; originals live in this repo and get symlinked to from the "Sources" directory in "Application Support":
-  - `10-4K.json`
-  - `10-Retina.json`
-  - `40-Mutt-4K.json`
-  - `40-Mutt-Retina.json`
-  - `70-Vim-4K.json`
-  - `70-Vim-Retina.json`
-- Parent profiles with common settings; originals live in this repo and get symlinked to from the "Dynamic Profiles" directory in "Application Support":
-  - `00-Base.json`
-  - `30-Mutt-Base.json`
-  - `60-Vim-Base.json`
+-   Just symlinks; changing what these points at causes iTerm2 to switch to a different profile:
+    -   `Mutt.json`
+    -   `Vim.json`
+    -   `Wincent.json`
+-   Actual profiles; originals live in this repo and get symlinked to from the "Sources" directory in "Application Support":
+    -   `10-4K.json`
+    -   `10-Retina.json`
+    -   `40-Mutt-4K.json`
+    -   `40-Mutt-Retina.json`
+    -   `70-Vim-4K.json`
+    -   `70-Vim-Retina.json`
+-   Parent profiles with common settings; originals live in this repo and get symlinked to from the "Dynamic Profiles" directory in "Application Support":
+    -   `00-Base.json`
+    -   `30-Mutt-Base.json`
+    -   `60-Vim-Base.json`
 
 ## What this all means
 
-* Because these are symlinks, editing the files in this repo will have no effect until the next iTerm restart (it will notice changes made by Hammerspoon to the symlink targets, but not changes to the files themselves, because the files live in a directly that it is not monitoring).
-* Any edits you make to a dynamic profile from the iTerm UI are not written back to the filesystem: to update the JSON files, you must explicitly export the settings using the drop-down in the UI, and them manually merge them in here.
+-   Because these are symlinks, editing the files in this repo will have no effect until the next iTerm restart (it will notice changes made by Hammerspoon to the symlink targets, but not changes to the files themselves, because the files live in a directly that it is not monitoring).
+-   Any edits you make to a dynamic profile from the iTerm UI are not written back to the filesystem: to update the JSON files, you must explicitly export the settings using the drop-down in the UI, and them manually merge them in here.
 
 ## A note about the `vim://` URL scheme
 
index dcf0d5c30899834546fffc2016e2ae940a60d6f7..2e4c2f76b791ec384d0bca32204dd955d2b52bbf 100644 (file)
@@ -1,6 +1,6 @@
 Configures launchd to:
 
-- Persist overrides of ridiculously low ulimit values in macOS.
-- Set locale-related environmental variables for the benefit of GUI apps.
+-   Persist overrides of ridiculously low ulimit values in macOS.
+-   Set locale-related environmental variables for the benefit of GUI apps.
 
 See: http://unix.stackexchange.com/questions/108174/how-to-persist-ulimit-settings-in-osx-mavericks
index aeee904ba5bce6e0cf61d4249feda293806402c0..a0ef1b413f3d442dde827d944acce424bfa62727 100644 (file)
@@ -79,7 +79,9 @@ task('compile Command-T', async () => {
 });
 
 task('build LanguageClient-neovim', async () => {
-    const base = path.aspect.join('files/.vim/pack/bundle/opt/LanguageClient-neovim');
+    const base = path.aspect.join(
+        'files/.vim/pack/bundle/opt/LanguageClient-neovim'
+    );
 
     await command('./install.sh', [], {
         chdir: base,
@@ -90,9 +92,13 @@ task('build LanguageClient-neovim', async () => {
 task('create spell file', async () => {
     const spellfile = path.aspect.join('files/.vim/spell/en.utf-8.add');
 
-    await command('nvim', ['-u', 'NONE', '-N', '-c', `mkspell! ${spellfile} | quit`], {
-        creates: `${spellfile}.spl`
-    });
+    await command(
+        'nvim',
+        ['-u', 'NONE', '-N', '-c', `mkspell! ${spellfile} | quit`],
+        {
+            creates: `${spellfile}.spl`,
+        }
+    );
 });
 
 task('update bundle', async () => {
diff --git a/fig/README.md b/fig/README.md
new file mode 100644 (file)
index 0000000..9fb55b5
--- /dev/null
@@ -0,0 +1,35 @@
+# Fig: A configuration "framework"
+
+### How this repo works
+
+0. **2009**: Originally, the repo was just a [collection of files](https://github.com/wincent/wincent/tree/61a7e2a830edb757c59e542039131e671da8b154) with no installation script.
+1. **2011-2015**: I [created a `bootstrap.rb` script](https://github.com/wincent/wincent/commit/e29b2818c487529eb4e7662a23df56445b448fe3) ([final version here](https://github.com/wincent/wincent/blob/94fb4d50243b97cd0c92a5691ac430353a5299a0/bootstrap.rb)) for performing set-up.
+1. **2015**: I [briefly experimented](https://github.com/wincent/wincent/commit/4efdb1f97685bf735b068835adced059cd721096) with using a `Makefile` ([final version here](https://github.com/wincent/wincent/blob/01b37a546b92f60e659a8153067353d58805a009/Makefile)).
+1. **2015-2020**: I [switched to Ansible](https://github.com/wincent/wincent/commit/375f27a6ea6fdd78fcf6614d3af5335da7a9f5ef) (completing the transition in [cd98e9aaab](https://github.com/wincent/wincent/commit/cd98e9aaab82b1983aeab839d4f28260d6e19919)).
+1. **2020-present**: I started [feeling misgivings about the size of the dependency graph](https://github.com/wincent/wincent/issues/82) and in truth I was probably using less than 1% of Ansible's functionality, so moved to the current set-up, which is described below.
+
+The goal was to replace Ansible with some handmade scripts using the smallest dependency graph possible. I original [tried](https://github.com/wincent/wincent/commit/8809a1681cfd8fd02eb40113d2485d7cadc10e4c) out [Deno](https://deno.land/) because that would enable me to use TypeScript with no dependencies outside of Deno itself, however I [gave up on that](https://github.com/wincent/wincent/commit/a213ddf69d3213882808b5c5ff0e000bcd83fe98) when I saw that editor integration was still very nascent. So I went with the following:
+
+-   [n](https://github.com/tj/n) ([as a submodule](https://github.com/wincent/wincent/tree/master/vendor)) and some [hand-rolled Bash scripts](https://github.com/wincent/wincent/tree/master/bin) to replace [virtualenv](https://virtualenv.pypa.io/) and friends ([Python](https://www.python.org/), [pip](https://pypi.org/project/pip/)).
+-   [Yarn](https://github.com/yarnpkg/yarn/) ([vendored](https://github.com/wincent/wincent/commit/26adf86d4c742390537be4dc1572f93a97bc3e68)) to install [TypeScript](https://www.typescriptlang.org/).
+
+Beyond that, there are no dependencies outside of the [Node.js](https://nodejs.org/en/) standard library. I use [Prettier](https://prettier.io/) to format code, but I invoke it via `npx` which means the [yarn.lock](https://github.com/wincent/wincent/blob/master/yarn.lock) remains basically empty. Ansible itself is replaced by [a set of self-contained TypeScript scripts](https://github.com/wincent/wincent/tree/master/src). Instead of YAML configuration files containing "declarative" configuration peppered with Jinja template snippets containing Python and filters, we just use TypeScript for everything. Instead of [Jinja template files](https://jinja.palletsprojects.com/), we use ERB/JSP-like templates that use embedded JavaScript when necessary.
+
+Because I need a name to refer to this "set of scripts", it's called Fig (a play on "Config"). Overall structure remains similar to Ansible, but I made some changes to better reflect the use case here. While Ansible is made to orchestrate multiple (likely remote) hosts, Fig is for configuring one local machine at a time.
+
+| Ansible                                                                                                                         | Fig                                                                                                             |
+| ------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
+| **Hosts:** Machines to be configured (possibly remote)                                                                          | n/a (always the current, local machine)                                                                         |
+| **Groups:** Collections of hosts, so you can conveniently target multiple hosts without having to address each one individually | **Profiles:** An abstract category indicating the kind of a host (eg. "work" or "personal")                     |
+| **Inventory:** A list of hosts (or groups of hosts) to be managed                                                               | n/a ("project.json" file contains map from hostname to profile to be applied)                                   |
+| **Roles:** Capabilities that a host can have (eg. webserver, file-server etc)                                                   | **Aspects:** Logical groups of functionality to be configured (eg. dotfiles, terminfo etc)                      |
+| **Tasks:** Operations to perform (eg. installing a package, writing a file                                                      | **Tasks:** Same as Ansible.                                                                                     |
+| **Plays:** A mapping between hosts (or groups) and the tasks to be performed on them                                            | n/a (it's just a file containing tasks)                                                                         |
+| **Playbooks:** Lists of plays                                                                                                   | n/a ("project.json" file contains a map from platform to the aspects that should be set up on a given platform) |
+| **Tags:** Keywords that can be applied to tasks and roles, useful for selecting them to be run                                  | n/a (not needed)                                                                                                |
+| **Facts:** (Inferred) attributes of hosts                                                                                       | **Attributes:** Same as Ansible, but with a better name                                                         |
+| **Vars:** (Declared) values that can be assigned to groups, hosts or roles                                                      | **Vars:** Same as Ansible, but belong to profiles and aspects                                                   |
+| **Modules:** Units of code that implement operations (ie. these are what tasks use to actually do the work)                     | **Operations:** Code for performing operations                                                                  |
+| **Templates:** Jinja templates with embedded Python and "filters"                                                               | **Templates:** ERB templates with embedded JavaScript                                                           |
+| **Files:** Raw files that can be copied using modules                                                                           | **Files:** Raw files that can be copied using operations                                                        |
+| **Syntax:** YAML with interpolated Jinja syntax containing Python and variables                                                 | **Syntax:** TypeScript and (plain) JSON                                                                         |
index 83bfcd930cd8566536650ab568a80fdfeb76a6c2..b6ff70702d6bfb5f34b9c3a6b0f6a37e15ed2035 100644 (file)
@@ -9,8 +9,8 @@
     "license": "Unlicense",
     "scripts": {
         "ci": "yarn format:check",
-        "format:check": "npx prettier --check \"**/*.{js,json,ts}\" \"*.{md,ts}\" aspects/dotfiles/files/.zsh/liferay/bin/portool",
-        "format": "npx prettier --write \"**/*.{js,json,ts}\" \"*.{md,ts}\" aspects/dotfiles/files/.zsh/liferay/bin/portool"
+        "format:check": "npx prettier --check \"**/*.{js,json,md,ts}\" \"*.{md,ts}\" aspects/dotfiles/files/.zsh/liferay/bin/portool",
+        "format": "npx prettier --write \"**/*.{js,json,md,ts}\" \"*.{md,ts}\" aspects/dotfiles/files/.zsh/liferay/bin/portool"
     },
     "type": "module",
     "dependencies": {