From f6805c92113857e190897c144a4f67b27789db95 Mon Sep 17 00:00:00 2001 From: Tommaso Negri Date: Mon, 10 Aug 2026 22:30:12 +0200 Subject: update docs --- Sources/bar/bar.docc/bar.md | 26 +++++-- Sources/bar/bar.docc/command.md | 24 ++++++ Sources/bar/bar.docc/commands.md | 50 ------------- Sources/bar/bar.docc/gestures.md | 37 ++++++++++ Sources/bar/bar.docc/hide-show.md | 19 +++++ Sources/bar/bar.docc/highlighting.md | 37 ++++++++++ Sources/bar/bar.docc/how-it-works.md | 36 +++++++++ Sources/bar/bar.docc/installation.md | 52 ------------- Sources/bar/bar.docc/manual-updates.md | 28 ------- Sources/bar/bar.docc/patches.md | 90 +++++++++++++++++++++++ Sources/bar/bar.docc/patches/patch-font-offset.md | 26 +++++++ Sources/bar/bar.docc/philosophy.md | 34 --------- Sources/bar/bar.docc/refresh.md | 29 ++++++++ Sources/bar/bar.docc/run-at-login.md | 53 +++++++++++++ 14 files changed, 371 insertions(+), 170 deletions(-) create mode 100644 Sources/bar/bar.docc/command.md delete mode 100644 Sources/bar/bar.docc/commands.md create mode 100644 Sources/bar/bar.docc/gestures.md create mode 100644 Sources/bar/bar.docc/hide-show.md create mode 100644 Sources/bar/bar.docc/highlighting.md create mode 100644 Sources/bar/bar.docc/how-it-works.md delete mode 100644 Sources/bar/bar.docc/manual-updates.md create mode 100644 Sources/bar/bar.docc/patches.md create mode 100644 Sources/bar/bar.docc/patches/patch-font-offset.md delete mode 100644 Sources/bar/bar.docc/philosophy.md create mode 100644 Sources/bar/bar.docc/refresh.md create mode 100644 Sources/bar/bar.docc/run-at-login.md (limited to 'Sources') diff --git a/Sources/bar/bar.docc/bar.md b/Sources/bar/bar.docc/bar.md index 3d8b2ee..0788349 100644 --- a/Sources/bar/bar.docc/bar.md +++ b/Sources/bar/bar.docc/bar.md @@ -14,25 +14,39 @@ If you specify the interval, the block will re-run the command with such frequen ## Topics +### Before you start + +- + ### Getting started - +- + +### Customisation + - +- - ``Config`` - ``HEX`` +### Bar + +- + ### Blocks -- -- +- +- +- +- - ``Block`` - ``Cell`` -- ``Runner`` -- ``Notifier`` -### Design +### Models -- +- ``Runner`` +- ``Notifier`` ### Views diff --git a/Sources/bar/bar.docc/command.md b/Sources/bar/bar.docc/command.md new file mode 100644 index 0000000..c94862e --- /dev/null +++ b/Sources/bar/bar.docc/command.md @@ -0,0 +1,24 @@ +# Command + +How the block's command is executed. + +Each block runs its ``Config-swift.enum/Block/command`` as a shell script via `/bin/sh -c`. +The standard output is captured and **each line becomes one ``Cell``** in the bar. +Cells are laid out horizontally in the order they appear. + +```shell +# A single-line command produces one cell +echo "Hello, world" + +# Multi-line output produces multiple cells +echo "first cell" +echo "second cell" +``` + +## Environment variables + +Each command inherits the `bar` process environment plus a `BLOCK` variable that holds the ``Block/name``. + +> Important: Since the environment is inherited by the `bar` process, there is no guarantee that the script will always receive the same set of variables. +For example, if you run `bar` from your shell, you'll probably have available the custom `PATH` you set. +On the contrary, if you run `bar` from a launch agent, you'll probably not have the same custom `PATH` set. diff --git a/Sources/bar/bar.docc/commands.md b/Sources/bar/bar.docc/commands.md deleted file mode 100644 index 4c00bfe..0000000 --- a/Sources/bar/bar.docc/commands.md +++ /dev/null @@ -1,50 +0,0 @@ -# Commands - -How a block runs its command and what you can do with it. - -Each block runs its ``Config-swift.enum/Block/command`` as a shell script via `/bin/sh -c`. -The standard output is captured and **each line becomes one ``Cell``** in the bar. -Cells are laid out horizontally in the order they appear. - -```shell -# A single-line command produces one cell -echo "Hello, world" - -# Multi-line output produces multiple cells -echo "first cell" -echo "second cell" -``` - -## Highlighting cells - -Prefix a line with `&!` to apply a highlight background color. -The highlight level is a positive integer that indexes into ``Config-swift.enum/highlights`` (1-based). - -```shell -echo "&!1 workspace 1" # highlighted with Config.highlights[0] -echo "&!2 workspace 2" # highlighted with Config.highlights[1] -echo "workspace 3" # no highlight -``` - -Highlight colors were imagined specifically for distinguishing cells within a group. E.g: showing window manager workspaces and which one is active. - -## Environment variables - -Each command inherits the `bar` process environment, plus these extras: - -| Variable | What holds | When set | Example value | -|---|---|---|---| -| `BLOCK` | The name of the block | Always | `"clock"` | -| `BUTTON` | The mouse button number | On mouse click inside the block | `"0"` (left), `"1"` (right), `"2"` (middle) | -| `SCROLL` | The scroll direction | On scroll over the block | `"UP"`, `"DOWN"`, `"LEFT"`, `"RIGHT"` | - -This lets a single script adapt its behaviour based on which block called it or what interaction just happened: - -```shell -#!/bin/sh -if [ "$BLOCK" = "clock" ]; then - date '+%a %d, %H:%M:%S' -elif [ -n "$BUTTON" ]; then - echo "clicked button $BUTTON" -fi -``` diff --git a/Sources/bar/bar.docc/gestures.md b/Sources/bar/bar.docc/gestures.md new file mode 100644 index 0000000..e9cceed --- /dev/null +++ b/Sources/bar/bar.docc/gestures.md @@ -0,0 +1,37 @@ +# Gestures + +React to click or scroll gestures on a block. + +Each time you click or scroll over a ``Block``, the command is executed and you can optionally react to it. + +## Environment variables + +When a ``Block/command`` is executed by a gesture, a couple environment variables are set to let you know what just happened. + +| Variable | What holds | When set | Example value | +|---|---|---|---| +| `BUTTON` | The mouse button number | On click | `"0"` (left), `"1"` (right), `"2"` (middle), etc | +| `SCROLL` | The scroll direction | On scroll | `"UP"`, `"DOWN"`, `"LEFT"`, `"RIGHT"` | + +## React to gestures + +Here an example of using the `BUTTON` variable to toggle (play/pause) or stop [mpd](https://www.musicpd.org/): + +```shell +case $BUTTON in + (0) mpc toggle >/dev/null ;; + (2) mpc stop >/dev/null ;; +esac +``` + +Here an example of using the `SCROLL` variable to adjust the volume: + +```shell +increaseVolume() { osascript -e "set volume output volume (output volume of (get volume settings) + 10)" } +decreaseVolume() { osascript -e "set volume output volume (output volume of (get volume settings) - 10)" } + +case $SCROLL in + (UP) increaseVolume ;; + (DOWN) decreaseVolume ;; +esac +``` diff --git a/Sources/bar/bar.docc/hide-show.md b/Sources/bar/bar.docc/hide-show.md new file mode 100644 index 0000000..e36a1fd --- /dev/null +++ b/Sources/bar/bar.docc/hide-show.md @@ -0,0 +1,19 @@ +# Hide & Show + +Send a notification that hides or shows the bar. + +Use the standard `notifyutil` program to post a Darwin notification that hides or shows the bar on-demand. + +## Hide + +```shell +notifyutil -p bar.hide +``` + +> Note: Hiding the bar won't stop blocks from being refreshed. + +## Show + +```shell +notifyutil -p bar.show +``` diff --git a/Sources/bar/bar.docc/highlighting.md b/Sources/bar/bar.docc/highlighting.md new file mode 100644 index 0000000..8bd737c --- /dev/null +++ b/Sources/bar/bar.docc/highlighting.md @@ -0,0 +1,37 @@ +# Highlighting + +Change the background color of a block's cell on-demand. + +You can assign a background color to each ``Cell`` within a ``Block`` directly from the shell script. +Since the colors are assigned at runtime, highlights can be used not only for customising the appearance but also for assigning meaning or status to a particular item of the bar. + +Also, since the color is applied to a single cell and not to the entire block, this feature is perfect for building grouped content like a workspace indicator or any other situation where you want to see which item is selected within a group. + +## Define the highlights + +Before assigning a color to a cell, you have to define the available ``Config-swift.enum/highlights`` in the ``Config`` file. + +```swift +// Sources/bar/Config.swift + +enum Config { + static let highlights: [Color] = [.hex("#ff0000"), .hex("#0000ff"), .purple] +} +``` + +> Note: The order in which you define the highlights matters. +*bar* will use the index of the elements in the array as the "level" of highlight you want to apply. +See [set the highlight](#Set-the-highlight) for more information. + +## Set the highlight + +In a shell script, prefix an output line with `&!` to apply the desired highlight. +You are not required to leave an empty space after special notation. + +```shell +echo "&!1 workspace 1" # highlighted with Config.highlights[0] +echo "&!2 workspace 2" # highlighted with Config.highlights[1] +echo "workspace 3" # no highlight +``` + +> Important: The highlight level is a positive integer that indexes into ``Config-swift.enum/highlights`` (1-based). diff --git a/Sources/bar/bar.docc/how-it-works.md b/Sources/bar/bar.docc/how-it-works.md new file mode 100644 index 0000000..b6efbd8 --- /dev/null +++ b/Sources/bar/bar.docc/how-it-works.md @@ -0,0 +1,36 @@ +# How it works + +How *bar* works and how it differs from most macOS programs. + +*bar* design is heavily inspired by the suite of [*suckless* tools](https://suckless.org/) for Linux. +These tools are vastly different from what you typically use on macOS. +They do not have configuration files, extraneous features, or a plugin/extension system. +Instead, they are focused on simplicity, frugality, and a DIY approach. + +We deliberately designed *bar* to be extremely limited, specific, and easy to understand, like a *suckless* tool. +This is not software you install, run, and forget about. +You're supposed to fully understand how it works, make it yours, and ultimately give back the enhancements you made to the community. + +## How customisation works + +*bar* does not read a configuration file somewhere on your system. +Instead, configuration happens directly in the source code by editing ``Config`` and rebuilding the software. +This approach allows us to keep the software extremely minimal and reliable, since all the possible errors are caught at build time. + +## No pre-built binaries + +Since the configuration requires you to modify the source code, it doesn't make sense to ship pre-built binaries of *bar*. +Therefore, you won't find it in Homebrew or in any other package manager. +The way to install *bar* is simply to download or clone the repository on your system and run `make install`. + +## How to extend the functionality + +*bar* already does a lot out of the box, but it is deliberately more limited compared to other solutions like [SketchyBar](https://felixkratz.github.io/SketchyBar/). +What if you need a specific feature that is not available? +Well, you can build it or patch it yourself. + +*bar* aims to stay focused and minimal, so it can be read through and understood in roughly half an hour. +You're more than encouraged to apply to extend the software, write your own features, and ultimately publish them for the entire community. + +This approach is far more powerful than a plugin/extension ecosystem because you're not limited to what we, as the main developers, decide you can customise or change. +You own the source code, therefore you are free to do whatever you want. diff --git a/Sources/bar/bar.docc/installation.md b/Sources/bar/bar.docc/installation.md index 55bbae6..272882e 100644 --- a/Sources/bar/bar.docc/installation.md +++ b/Sources/bar/bar.docc/installation.md @@ -41,55 +41,3 @@ If you don't have `make`, build directly with the Swift Package Manager: swift build -c release cp .build/release/bar /usr/local/bin/ ``` - -## Run at login - -It is fine to run `bar` manually while you're editing and customising the source code. -Although, as soon as you're happy with your build is a good idea to create a launch agent that can start the program for you. - -Copy the example down below in a `plist` file inside the `~/Library/LaunchAgents/` directory. - -> Tip: It is best practice to use [reverse domain name notation](https://en.wikipedia.org/wiki/Reverse_domain_name_notation) for the filename. - -Adjust the example as you see fit. -For the full file specification run: - -```shell -man launchd.plist -``` - -You can than register the launch agent like so: - -```shell -launchctl load ~/Library/LaunchAgents/house.panini.bar.plist -``` - -### Example launch agent - -```plist - - - - - Label - house.panini.bar - - ProgramArguments - - ~/.local/bin/bar - - - RunAtLoad - - - KeepAlive - - - StandardOutPath - /tmp/bar/bar.log - - StandardErrorPath - /tmp/bar/bar.err - - -``` diff --git a/Sources/bar/bar.docc/manual-updates.md b/Sources/bar/bar.docc/manual-updates.md deleted file mode 100644 index c5157e5..0000000 --- a/Sources/bar/bar.docc/manual-updates.md +++ /dev/null @@ -1,28 +0,0 @@ -# Manual refreshes - -How to trigger a block update on-demand. - -*bar* implements a very basic way to manually signal a block to refresh its content. -This is done by posting a [Darwin notification](https://developer.apple.com/documentation/notifications) from the shell. - -## Triggering a refresh - -Use `notifyutil` (bundled with macOS) to post a notification: - -```shell -notifyutil -p bar.touch. -``` - -Replace `` with the block's name (e.g. `clock`, `battery`). -If multiple blocks share the same name, a single notification refreshes them all. - -## Use cases - -Manual updates are useful for blocks that react to external events: - -- **Window managers** - refresh when the workspace or focused app changes. -- **Volume indicator** — refresh when the sound output changes. -- **Network monitor** — poll only when the interface state flips. -- **Now playing** — update when the current track changes. - -Combine with a launch agent or a shell hook that posts the notification whenever the relevant system state changes. diff --git a/Sources/bar/bar.docc/patches.md b/Sources/bar/bar.docc/patches.md new file mode 100644 index 0000000..1a356c9 --- /dev/null +++ b/Sources/bar/bar.docc/patches.md @@ -0,0 +1,90 @@ +# Patches + +Extend the program with additional functionality. + +A *patch* is a set of source code changes that add a specific feature to a program. +Unlike plugins or extensions, patches modify the program directly — you edit the source, rebuild, and the new functionality becomes part of the binary. + +The patch system is heavily inspired by the [*suckless* tools](https://suckless.org/hacking/) community, where this is the primary way to share and distribute enhancements. +Patches keep the core of *bar* minimal and focused, while allowing anyone to extend it with exactly what they need. + +> Tip: Just like suckless, we encourage you to create and share your own patches with the community. + +## How patches work + +A patch is distributed as a `.patch` file and applied with the `patch` command. +The file contains a diff of the changes needed to add a specific feature. + +For example, to apply a patch from the *bar* collection: + +```shell +curl -sL https://raw.githubusercontent.com/paninihouse/bar/refs/heads/master/patches/bar-font_offset-20260810-11d813c.patch | patch -p1 +``` + +After applying the patch, rebuild the program: + +```shell +make install +``` + +> Important: If a patch does not apply cleanly (e.g., because your local code has diverged), you can either apply it manually by editing the source files by hand, or revert your changes with `git checkout .` and start from a clean copy. + +## How to make a patch + +Creating a patch is straightforward if you already made the changes in your local copy: + +1. Make sure your working directory is a git repository. +2. Stage all the changes you want to include in the patch. +3. Run `git diff` to generate the patch file. + +For example: + +```shell +git diff > my-awesome-feature.patch +``` + +If you want to submit the patch to the community, upload it somewhere publicly accessible (e.g., a GitHub repo or a personal website) and link it in the patch documentation. + +> Important: A good patch is focused on a single feature and does not include unrelated changes. +> This makes it easier for others to review and apply only what they need. + +### Building upon other patches + +Patches can depend on other patches. +If your feature requires a change that is already covered by an existing patch, simply list it as a prerequisite. + +For example, a patch that adds a new styling option might depend on the patch because it touches the same area of the codebase. +When publishing, make sure to clearly document which patches (if any) must be applied first. + +This modular approach lets the community mix and match features without duplicating work. + +## Naming and publishing + +When publishing a patch, use a descriptive file name that follows the convention: + +``` +bar---.patch +``` + +For example: + +``` +bar-font_offset-20260810-11d813c.patch +``` + +The date pinpoints which version of the code the patch was made against, and the commit hash makes it easy to look up the exact state of the repository at that point. + +To publish, upload the patch somewhere publicly accessible (e.g., the *bar* GitHub repo, a personal website, or a gist) and add a new article in the documentation with: + +- A short description of what the patch does. +- Any configuration options it adds. +- The installation instructions or a download link to the raw `.patch` file. +- The author(s). + +> Tip: Keep the patch documentation in sync with the actual patch file. If you update the code, regenerate the patch and update the date and commit hash in both the file name and the documentation. + +## Topics + +### Appearance + +- diff --git a/Sources/bar/bar.docc/patches/patch-font-offset.md b/Sources/bar/bar.docc/patches/patch-font-offset.md new file mode 100644 index 0000000..9b2d841 --- /dev/null +++ b/Sources/bar/bar.docc/patches/patch-font-offset.md @@ -0,0 +1,26 @@ +# Font offset + +Adjust font centering with a vertical offset. + +This patch adds a `fontOffset` option (Double) to ``Config``. +Set it to a negative value to move the text within a ``Cell`` upward, set it to a positive value to move it downward. + +```swift +enum Config { + /// The vertical offset that can be used to adjust font centering. + /// + /// A negative value will move the text upward, while a positive + /// value will move it downward. + static let fontOffset: Double = -0.5 +} +``` + +## Installation + +```shell +curl -sL https://raw.githubusercontent.com/paninihouse/bar/refs/heads/master/patches/bar-font_offset-20260810-11d813c.patch | patch -p1 +``` + +## Author + +Tommaso Negri [@tommasongr](https://github.com/tommasongr) diff --git a/Sources/bar/bar.docc/philosophy.md b/Sources/bar/bar.docc/philosophy.md deleted file mode 100644 index 6c9764b..0000000 --- a/Sources/bar/bar.docc/philosophy.md +++ /dev/null @@ -1,34 +0,0 @@ -# Design philosophy - -*bar* design is heavily inspired by the suite of [suckless tools](https://suckless.org/) for Linux. -These tools are very different from what you typically have on macOS. -They do not have configuration files, extraneous features, or a plugin/extension system. -Instead, they are focused on simplicity, frugality, and a DIY approach. - -We deliberately designed *bar* to be extremely limited, specific, and easy to understand, like a suckless tool. -This is not software you install, run, and forget about. -You're supposed to fully understand how it works, make it your own, and ultimately give back your enhancements to the community. - -## How customization works - -*bar* does not read a configuration file somewhere on your system. -Instead, configuration happens directly in the source code by editing ``Config`` and rebuilding the software. -This approach allows us to keep the software extremely minimal and reliable, since all the possible errors are caught at build time. - -## No pre-built binaries - -Since the configuration requires you to modify the source code, it doesn't make sense to ship pre-built binaries of *bar*. -Therefore, you won't find it in Homebrew or in any other package manager. -The way to install *bar* is simply to download or clone the repository on your system and run . - -## How to extend the functionality - -*bar* already does a lot out of the box, but it is deliberately more limited compared to other solutions like [SketchyBar](https://felixkratz.github.io/SketchyBar/). -What if you need a specific feature that is not available? -Well, you can build it or patch it yourself. - -*bar* aims to stay focused and minimal, so it can be read through and understood in roughly half an hour. -You're more than encouraged to apply patches to extend the software, write your own features, and ultimately publish them for the entire community. - -This approach is far more powerful than a plugin/extension ecosystem because you're not limited to what we, as the main developers, decide you can customize or change. -You own the source code, therefore you are free to do whatever you want. diff --git a/Sources/bar/bar.docc/refresh.md b/Sources/bar/bar.docc/refresh.md new file mode 100644 index 0000000..43e803e --- /dev/null +++ b/Sources/bar/bar.docc/refresh.md @@ -0,0 +1,29 @@ +# Refresh + +Refresh the block manually or on an interval. + +## Based on an interval + +Adjust the ``Block/interval`` (in seconds) of a ``Block`` to automatically execute the command on that base. + +```swift +// Sources/bar/Config.swift + +enum Config { + static let blocks: [Block] = [ + Block(name: "clock", placement: .right, command: "date '+%a %d, %H:%M:%S'", interval: 1), + ] +} +``` + +## Manually + +Use the standard `notifyutil` program to post a Darwin notification that forces the block to be refreshed instantly, regardless of the ``Block/interval``. + +```shell +notifyutil -p bar.touch. +``` + +Replace `` with the block's name (e.g. `clock`, `battery`). + +> Note: If multiple blocks share the same name, a single notification refreshes them all. diff --git a/Sources/bar/bar.docc/run-at-login.md b/Sources/bar/bar.docc/run-at-login.md new file mode 100644 index 0000000..43e7a6c --- /dev/null +++ b/Sources/bar/bar.docc/run-at-login.md @@ -0,0 +1,53 @@ +# Run at login + +How to start the program automatically at login. + +It is fine to run `bar` manually while you're editing and customising the source code. +Although, as soon as you're happy with your build is a good idea to create a launch agent that can start the program for you. + +Copy the example down below in a `plist` file inside the `~/Library/LaunchAgents/` directory. + +> Tip: It is best practice to use [reverse domain name notation](https://en.wikipedia.org/wiki/Reverse_domain_name_notation) for the filename. + +Adjust the example as you see fit. +For the full file specification run: + +```shell +man launchd.plist +``` + +You can than register the launch agent like so: + +```shell +launchctl load ~/Library/LaunchAgents/house.panini.bar.plist +``` + +### Example + +```plist + + + + + Label + house.panini.bar + + ProgramArguments + + ~/.local/bin/bar + + + RunAtLoad + + + KeepAlive + + + StandardOutPath + /tmp/bar/bar.log + + StandardErrorPath + /tmp/bar/bar.err + + +``` -- cgit v1.2.3