Last active
October 30, 2025 16:55
-
-
Save sleekweasel/a415fd1c5f80f79ec370d1d341340faf to your computer and use it in GitHub Desktop.
A copy-pasteable shell-based interactive line editor, for when I don't have vim in a container and don't want to install it for some reason.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Deliberately compact for easy copy/paste install | |
| set -o nounset -o errexit -o pipefail | |
| trap 'echo Aborted. Renaming "$EDIT" with appended date ; set -x ; mv -n -- "$EDIT" "$EDIT$(date +%F.%T)" || : ; exit 42' INT TERM | |
| if ! [[ -f "$1" ]] ; then echo "Usage: $0 file-to-edit. Did not see file '$1'" ; exit 42 ; fi | |
| FILE="$1"; EDIT="$1~" | |
| if [[ -f "$EDIT" ]] && ! diff -u -- "$FILE" "$EDIT" ; then | |
| echo Resolve or ignore above diffs. Quitting. ; echo "rm $EDIT" ; exit 42 | |
| fi | |
| cp "$FILE" "$EDIT" | |
| help() { echo "Try" ; grep -E ') *#' -- "$0" ; echo "And ^d to abort" ; } | |
| unodiff() { diff -u -- "$1" "$2" && echo (no diff) || echo (diff ends) ; } | |
| help | |
| while IFS= read -erp ':' REPLY || : ; do | |
| case "$REPLY" in | |
| d*) # e.g. d - diff vs original | |
| unodiff "$FILE" "$EDIT" ;; | |
| p*|.p*) # e.g. p or p 10 or p 4,6 or p /hello/ - print line/s | |
| cat -n -- "$EDIT" | sed -n "${REPLY#*p} p" ;; | |
| s\ *) # e.g. s 4,6 s/find/replace/ s!a/b!c/d! (any sed command like 's 5d' or 's 5i insert-before' or 's 5a insert-after' with \ for leading space ) | |
| TMP=$(mktemp) ; sed -- "${REPLY#s}" "$EDIT" > "$TMP" || : ; unodiff "$EDIT" "$TMP" ; mv -- "$TMP" "$EDIT" ;; | |
| i\ *) # e.g. i 18 - multiline insert before line 18 | |
| echo "Type multiple lines starting with the new line, end with ^D" | |
| TMP=$(mktemp) ; n=$(( ${REPLY#i } )) ; ( (( n > 1 )) && head -n "$((n-1))" -- "$EDIT" || : ; cat ; tail -n "+$n" "$EDIT" ) > "$TMP" | |
| unodiff "$EDIT" "$TMP" ; mv "$TMP" "$EDIT" ;; | |
| qs*|sq*|wq|:wq) # Quit and save | |
| echo "Saving $EDIT to $FILE" ; mv -- "$EDIT" "$FILE" ; exit 0 ;; | |
| qq*) # Quit without saving | |
| echo "Quit without saving. Renaming $EDIT with appended date" ; set -x ; mv -- "$EDIT" "$EDIT$(date +%F.%T)" ; exit 1 ;; | |
| '') ;; | |
| *) | |
| echo "Don't know '$REPLY'" ; help ;; | |
| esac | |
| done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment