friendly-name.fish

  1function friendly-name --description "Emit random friendly adjective-noun names"
  2    argparse 'h/help' 'n/count=' 'e/exclude=' 'exclude-file=' 'exclude-stdin' -- $argv
  3    or return 1
  4
  5    if set -q _flag_help
  6        echo "Usage: friendly-name [OPTIONS]"
  7        echo
  8        echo "Emit random friendly adjective-noun names."
  9        echo
 10        echo "Options:"
 11        echo "  -n, --count COUNT       Number of names to emit (default: 1)"
 12        echo "  -e, --exclude NAME      Exclude a specific name; may be repeated"
 13        echo "      --exclude-file PATH Read newline-delimited excludes from file"
 14        echo "      --exclude-stdin     Read newline-delimited excludes from stdin"
 15        echo "  -h, --help              Show this help message"
 16        return 0
 17    end
 18
 19    set -l adjectives \
 20        ancient autumn bitter billowing black blue bold brave broken calm \
 21        clever cold cool crimson damp dark dawn delicate dry eager \
 22        empty falling fragrant frosty fuzzy gentle golden green hidden holy \
 23        icy keen late light lingering little lively long lucky merry \
 24        misty muddy nameless noble old patient purple quiet red rough \
 25        shy silent small sparkling spring steady still swift twilight wandering \
 26        warm weathered white wild winter wispy withered young zippy \
 27        bright brisk crystal dusty faint fierce floral free fresh \
 28        great happy high huge kind loud majestic mild pale \
 29        pleasant polished proud quick ripe rolling rose royal \
 30        serene sharp silver sleek smooth snowy soft spiced \
 31        stout strange strong summer sunny sweet tall tender \
 32        tiny vast velvet vivid wide wondrous
 33
 34    set -l nouns \
 35        aurora badger beagle breeze brook cabin canyon cedar cliff cloud \
 36        comet coral crane creek delta dew dune eagle ember feather \
 37        fern field finch fire flora forest fox frog frost gazelle \
 38        glacier grass grove haven haze hill island kite lagoon lake \
 39        leaf lemur lily lynx marsh meadow mesa mist moon moose \
 40        mountain oak oasis otter owl panda peak pebble pine pond \
 41        rain ridge ripple river shadow sky smoke snow star stone \
 42        stream sun thunder tree tundra valley vortex wave wind \
 43        ash basin bear birch bloom blossom boulder cherry \
 44        cove crystal daisy deer echo elk fawn flame flower \
 45        gale garden geode glen gorge gull hawk heron iris \
 46        ivy jay jewel lark loon lotus lupine maple moss \
 47        nest orchid osprey path petal plum poppy prairie \
 48        quartz quail rabbit reef robin rose sage sail sequoia \
 49        shell shore shrew sparrow spruce storm summit swallow \
 50        swan swift thistle thorn thrush tide trail trout \
 51        tulip violet willow wing wren
 52
 53    set -l count 1
 54    if set -q _flag_count
 55        set count $_flag_count
 56
 57        if not string match -qr '^[1-9][0-9]*$' -- $count
 58            echo "friendly-name: --count must be a positive integer" >&2
 59            return 1
 60        end
 61    end
 62
 63    set -l excludes
 64    if set -q _flag_exclude
 65        set -a excludes $_flag_exclude
 66    end
 67
 68    if set -q _flag_exclude_file
 69        if not test -r "$_flag_exclude_file"
 70            echo "friendly-name: cannot read exclude file '$_flag_exclude_file'" >&2
 71            return 1
 72        end
 73
 74        while read -l line
 75            test -n "$line"; and set -a excludes $line
 76        end <"$_flag_exclude_file"
 77    end
 78
 79    if set -q _flag_exclude_stdin
 80        while read -l line
 81            test -n "$line"; and set -a excludes $line
 82        end
 83    end
 84
 85    set -l max_combinations (math (count $adjectives) \* (count $nouns))
 86    if test (math $max_combinations - (count $excludes)) -lt $count
 87        echo "friendly-name: not enough unique combinations available" >&2
 88        return 1
 89    end
 90
 91    set -l emitted
 92    set -l emitted_count 0
 93    set -l max_attempts 1000
 94
 95    while test $emitted_count -lt $count
 96        set -l attempts 0
 97
 98        while true
 99            set -l adjective $adjectives[(random 1 (count $adjectives))]
100            set -l noun $nouns[(random 1 (count $nouns))]
101            set -l name "$adjective-$noun"
102
103            if contains -- $name $excludes; or contains -- $name $emitted
104                set attempts (math $attempts + 1)
105
106                if test $attempts -ge $max_attempts
107                    echo "friendly-name: could not generate a unique name after $max_attempts attempts" >&2
108                    return 1
109                end
110
111                continue
112            end
113
114            echo $name
115            set -a emitted $name
116            set emitted_count (math $emitted_count + 1)
117            break
118        end
119    end
120end