Files
fish-config/functions/mv.fish
T
rootiest 859f14a6e9 feat(functions): tag CLASSIFICATION across functions/ and conf.d/
Audits every function's interaction with the C1-shadowed commands
(uses-shadow/bypasses-shadow) and general hazards (destructive,
network, blocking-prompt) per the CLASSIFICATION schema.

Delegated the initial mechanical sweep to agy, then reviewed every
file by hand: fixed a systemic double-blank-comment-line formatting
bug from the delegate pass, and corrected several judgment errors
found on review -- three false blocking-prompt tags where a fish
'read' was consuming piped input rather than waiting on a terminal
(open-url.fish, sbver.fish, play-media.fish, now untagged entirely),
a blocking-prompt tag on mkrep.fish despite its documented --yes
escape hatch, an untagged read in jobrunner.fish's own baseless
blocking-prompt claim (removed, along with a destructive tag on
cleanup of its own mktemp output -- the schema explicitly excludes
that), the same own-output-cleanup false positive on
_zellij_dump_log.fish's destructive tag, an interactive fzf-gated
confirmation on logs.fish and replay.fish's piped read misread the
same way as the first three, and a uses-shadow(mkdir) on mkcd.fish
that actually belongs to the _fish_mkdir_p helper it delegates to,
not to mkcd itself.
2026-09-21 21:26:44 -04:00

103 lines
3.4 KiB
Fish

# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 01-file-and-directory
#
# COMPONENT
# aliases/filesystem
#
# CLASSIFICATION
# bypasses-shadow(mv)
#
# SYNOPSIS
# mv [args...]
#
# DESCRIPTION
# Wraps mv to automatically collapse nested directories of the same name.
# When extracting archives results in redundant structures (e.g.,
# themes/themes/), calling mv themes/themes themes will gracefully
# move the inner contents up one level and remove the empty outer shell.
#
# Opinionated component (C1): when disabled via __fish_config_op_aliases,
# behaves exactly like bare command mv.
#
# ARGUMENTS
# args... Arguments forwarded to standard mv
#
# EXIT STATUS
# 0 Operation succeeded
# >0 Standard mv failure, or failed to collapse directory
#
# EXAMPLE
# mv ~/.config/btop/themes/themes ~/.config/btop/themes
function mv --wraps='mv' --description 'Move files with auto-collapse for nested directories'
# Opinionated guard (C1): fall back to bare command mv when disabled.
if not __fish_config_op_enabled (status current-function)
command mv $argv
return $status
end
# 1. Parse arguments to separate flags from paths
set -l paths
set -l flags
for arg in $argv
if string match -q -- "-*" "$arg"
set -a flags "$arg"
else
set -a paths "$arg"
end
end
# 2. Condition: exactly two path arguments provided
if test (count $paths) -eq 2
set -l src $paths[1]
set -l dst $paths[2]
# Condition: both arguments must be directories
if test -d "$src"; and test -d "$dst"
# Resolve to absolute paths to prevent relative path mismatches
set -l real_src (realpath "$src" 2>/dev/null)
set -l real_dst (realpath "$dst" 2>/dev/null)
if test -n "$real_src"; and test -n "$real_dst"
set -l src_dir (dirname "$real_src")
set -l src_base (basename "$real_src")
set -l dst_base (basename "$real_dst")
# 3. Intercept: child is directly inside parent, and names match perfectly
if test "$src_dir" = "$real_dst"; and test "$src_base" = "$dst_base"
echo "📦 Auto-collapsing nested directory: $src_base"
# Gather all items safely (includes hidden files, excludes . and ..)
set -l items (find "$real_src" -mindepth 1 -maxdepth 1)
set -l mv_status 0
if test -n "$items"
for item in $items
command mv $flags "$item" "$real_dst/"
if test $status -ne 0
set mv_status 1
end
end
end
# Clean up the inner directory if the move was entirely successful
if test $mv_status -eq 0
command rmdir "$real_src" 2>/dev/null
else
set_color yellow
echo "⚠️ Some items could not be moved. Nested directory preserved." >&2
set_color normal
end
return $mv_status
end
end
end
end
# 4. Fallback: Standard mv behavior for everything else
command mv $argv
end