Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,29 @@ Change Log
==========


## Unreleased

Repository and `curl | sh` installs only; the PyPI package is unaffected.

**Added**

- `install.sh` offers a command to link the launchers into
`/usr/local/bin`, which is on sudo's `secure_path` where
`~/.local/bin` is not. It prints the command rather than running it,
since nothing else in the installer needs a password, and it skips the
offer if something that is not ours already holds either name.
- `uninstall.sh` reports those links and gives the command to remove
them. It never touches them itself.
- Both scripts honour `SYS_BIN_DIR` for non-standard prefixes.

**Documentation**

- The README describes the `/usr/local/bin` option alongside the
full-path and `sudoedit` approaches.
- Corrected the account of when upstream stopped: the last substantive
change to `master` was 11 December 2019, not January 2021, which was
two README image URL edits.

## [v0.3.3](https://github.com/leancode/suplemon/tree/0.3.3) (2026-09-03)

**Fixed**
Expand Down
33 changes: 26 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ https://github.com/leancode/suplemon
This is an actively maintained fork of [richrd/suplemon](https://github.com/richrd/suplemon).

The original is a genuinely good editor and none of the design here is ours.
Upstream simply stopped: the last commit to `master` landed in January 2021,
the `dev` branch in June 2020, and 25 issues and 5 pull requests are still
open, some since 2016. Suplemon had also stopped running altogether on
Python 3.12 and newer, which is what prompted the fork.
Upstream simply stopped. The last change of any substance to `master` was on
11 December 2019; the only two commits since were README image URL edits in
January 2021. The `dev` branch last moved in June 2020. 25 issues and 5 pull
requests are still open, some since 2016. Suplemon had also stopped running
altogether on Python 3.12 and newer, which is what prompted the fork.

Since then this fork has:

Expand Down Expand Up @@ -155,13 +156,31 @@ That works because the launcher hard-codes an absolute path to the source
tree. `$HOME` is root's under sudo, so a launcher written in terms of
`$HOME` would look for the interpreter in the wrong place.

If you do this often, either add `~/.local/bin` to `secure_path` in
`visudo`, or use `sudoedit`, which copies the file to a temporary location,
If you do this often, link the launcher somewhere sudo already looks.
`/usr/local/bin` is on `secure_path` on every system I know of, so this makes
`sudo suplemon` work by name:

sudo ln -sf ~/.local/bin/suplemon /usr/local/bin/suplemon && sudo ln -sf ~/.local/bin/suplemon /usr/local/bin/se

`install.sh` prints this command for you, and skips it if something that is
not ours already sits at either name — a stream editor called `se` exists, and
silently replacing it would be rude.

Links rather than copies, so re-running `install.sh` keeps them current; a
copy would quietly go stale. The launcher holds an absolute path to your own
source tree, so these run your checkout whoever invokes them: fine on a
single-user machine, probably not on a shared one. `uninstall.sh` will not
remove them, since it only touches `~/.local`, but it does tell you they are
there.

The alternative is `sudoedit`, which copies the file to a temporary location,
opens it as you rather than as root, and copies it back:

SUDO_EDITOR=~/.local/bin/suplemon sudoedit /etc/hosts

`sudoedit` is the safer of the two: the editor never runs as root.
`sudoedit` is the safest of the three: the editor never runs as root at all,
so nothing it loads — modules, your config, a theme — is running with
privileges.


### Notes
Expand Down
32 changes: 32 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ set -eu
REPO_URL="https://github.com/leancode/suplemon.git"
SRC_DIR="$HOME/.local/src/suplemon"
BIN_DIR="$HOME/.local/bin"
# Where sudo can see it. Overridable for testing and odd prefixes.
SYS_BIN_DIR="${SYS_BIN_DIR:-/usr/local/bin}"
LAUNCHER="$BIN_DIR/suplemon"
SHORTCUT="$BIN_DIR/se"
PY_MIN="3.8"
Expand Down Expand Up @@ -221,6 +223,36 @@ LAUNCHER_EOF
[ -L "$SHORTCUT" ] && info " or: se [file]"
info "Press F1 inside the editor for help, Ctrl+Q to quit."

# Optional, and deliberately not done for you: this script installs
# entirely inside $HOME and never asks for a password. sudo replaces
# PATH with secure_path, which excludes ~/.local/bin but includes
# /usr/local/bin, so a copy there is what makes "sudo suplemon" work
# by name rather than by full path.
# Symlinks rather than copies, so they keep tracking the launcher when
# this script is re-run. Never suggest clobbering an "se" that is not
# ours: a stream editor of that name exists and could be installed.
usrlocal_ok=1
for f in "$SYS_BIN_DIR/suplemon" "$SYS_BIN_DIR/se"; do
if [ -e "$f" ] || [ -L "$f" ]; then
if ! grep -q 'SUPLEMON_HOME' "$f" 2>/dev/null &&
[ "$(readlink "$f" 2>/dev/null)" != "$LAUNCHER" ]; then
warn "$f exists and is not ours; leaving it alone"
usrlocal_ok=0
fi
fi
done
if [ "$usrlocal_ok" = "1" ] && { [ ! -e "$SYS_BIN_DIR/suplemon" ] || [ ! -e "$SYS_BIN_DIR/se" ]; }; then
printf '\n%sOptional.%s sudo replaces PATH with its own secure_path, which\n' "$B" "$N"
info "excludes $BIN_DIR. To use it with sudo, link the launcher"
info "into $SYS_BIN_DIR. This is the only step that needs a password:"
printf '\n %ssudo ln -sf %s %s/suplemon && sudo ln -sf %s %s/se%s\n' \
"$B" "$LAUNCHER" "$SYS_BIN_DIR" "$LAUNCHER" "$SYS_BIN_DIR" "$N"
info "Links, not copies, so re-running this script keeps them current."
info "They run your source tree, so keep them to machines you alone use."
elif [ "$usrlocal_ok" = "1" ]; then
ok "Linked into $SYS_BIN_DIR, so sudo can find it"
fi

# Anything the user still has to do goes last, so it is the final thing
# on screen rather than something scrolled away by later output. This
# script cannot set PATH for you: it runs in its own process, and a
Expand Down
18 changes: 18 additions & 0 deletions uninstall.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ set -eu

SRC_DIR="$HOME/.local/src/suplemon"
BIN_DIR="$HOME/.local/bin"
# Where the optional sudo-visible links live. Overridable for testing.
SYS_BIN_DIR="${SYS_BIN_DIR:-/usr/local/bin}"
LAUNCHER="$BIN_DIR/suplemon"
SHORTCUT="$BIN_DIR/se"
CONFIG_DIR="$HOME/.config/suplemon"
Expand Down Expand Up @@ -155,6 +157,22 @@ main() {
####################################################################
step "Left in place on purpose"
info "$BIN_DIR, because other programs live there"
# The README suggests linking the launchers into /usr/local/bin so sudo
# can find them. Those are root-owned and outside $HOME, and this script
# never asks for a password, so they are reported and left alone. Only
# ours are named: anything else at those paths is someone else's.
found=""
for f in "$SYS_BIN_DIR/suplemon" "$SYS_BIN_DIR/se"; do
if [ -L "$f" ] && [ "$(readlink "$f" 2>/dev/null)" = "$LAUNCHER" ]; then
found="$found $f"
elif [ -f "$f" ] && grep -q 'SUPLEMON_HOME' "$f" 2>/dev/null; then
found="$found $f"
fi
done
if [ -n "$found" ]; then
info "These, which need root to remove. Nothing here touches them:"
printf ' %ssudo rm -f%s%s\n' "$B" "$found" "$N"
fi
for f in "$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.profile"; do
if [ -f "$f" ] && grep -q 'Added by the Suplemon installer' "$f" 2>/dev/null; then
info "The PATH block in $f, since $BIN_DIR stays"
Expand Down
Loading