2
\$\begingroup\$

My intention is to POSIX-ly write one generalized function for running various text editors I use for different purposes through sudoedit, i.e. editing files as root safely. Safely = for instance, if a power loss occurs during the file edit; another example could be lost SSH connection, etc.


Originally, I had these Bash functions defined for this purpose in my .bash_aliases file:

function sucode
{
    export SUDO_EDITOR='/usr/bin/code --wait'
    sudoedit "$@"
}
function susubl
{
    export SUDO_EDITOR='/opt/sublime_text/sublime_text --wait'
    sudoedit "$@"
}
function suxed
{
    export SUDO_EDITOR='/usr/bin/xed --wait'
    sudoedit "$@"
}

Since yesterday, I'm trying to generalize that solution for other Linux users to be able to take advantage of it. Momentary peek:

# Text editing as root; The proper way through `sudoedit`.
sudoedit_internal()
{
    [ "${#}" -lt 3 ] && { printf '%s\n' 'sudoedit_internal(): Invalid number of arguments.' 1>&2; return; }
    editor_path=$( command -v "${1}" )
    [ -x "${editor_path}" ] || { printf '%s\n' "sudoedit_internal(): The editor path ${editor_path} does not exist on this system." 1>&2; return; }
    editor_wait_option=${2}
    shift 2
    env SUDO_EDITOR="${editor_path} ${editor_wait_option}" sudoedit "${@}"
}
# CLI
suvi()   { sudoedit_internal vi   '' "${@}"; }
sunano() { sudoedit_internal nano '' "${@}"; }
# GUI
sucode() { sudoedit_internal code -w "${@}"; }
susubl() { sudoedit_internal subl -w "${@}"; }
suxed()  { sudoedit_internal xed  -w "${@}"; }

These 5 editors I use. Please take that as an example only.

As I should not update this question any further, you can find the up-to-date version of this script snippet in my Unix & Linux Q&A.

\$\endgroup\$
3
\$\begingroup\$

It's good form to return non-zero on error. The not-optional option is a little ugly and an environment variable may work better.

Some extraneous syntax can go:

  • 1 before >&2 is implied
  • {} around unsubstituted dereferences doesn't add anything
  • echo is an alias for printf "%s\n"
  • testing for error instead of success allows test && echo && return without braces
  • command -v tests validity for you; no need to test again
  • you've moved the complexity into a function already; reward yourself by using aliases to invoke it
sudoedit_internal()
{
    [ $# -lt 2 ] && echo "sudoedit_internal(): Invalid number of arguments." >&2 && return 1
    ! command -v "$1" >/dev/null && echo "sudoedit_internal(): The editor $1 does not exist on this system." >&2 && return 1
    editor="$1"; shift 
    SUDO_EDITOR="$editor $opt" sudoedit "$@"
}

for ed in vi nano       ; do alias su$ed="opt=   sudoedit_internal $ed"; done
for ed in code subl xed ; do alias su$ed="opt=-w sudoedit_internal $ed"; done
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.