Skip to content

Instantly share code, notes, and snippets.

@RickCogley
Last active May 14, 2023 01:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RickCogley/8379d65b382d1cff58c1e3789d616b09 to your computer and use it in GitHub Desktop.
Save RickCogley/8379d65b382d1cff58c1e3789d616b09 to your computer and use it in GitHub Desktop.
Append to Dictionary File in nushell

Appending Words to a Dictionary File in Nushell

I call a dictionary file from my nupass.nu password generator command, which is simply a file with one Japanese word or phrase per line. I wanted to be able to easily add words to the dictionary file, followed by a quick git commit, hence this nushell script.

In this case, it's easy to just add those commands to nushell's env.nu instead of having them as a separate script file. Once added, I just reloaded nushell, and then it was just a matter of doing the following to add the words to the file:

> dict add onepiece golgo13 dragonball naruto doraemon 

See the screenshot below for what the output looks like.

Script Notes

A couple notes:

  • calls an environment variable "DICT_FILE_PATH" as default for the dict file path. Set it in env.nu like this:
    • let-env DICT_FILE_PATH = '/path/to/where/dict/file/lives/'
  • in the flags definition section, uses a "rest parameter" (...word) to accept any number of words, and allows you to override the path
  • uses a for loop to loop over the word or words in $word, checking if the word is already present or not, making lists of added and not added words, and passing any not-yet-present words to a utility function append_file to add to the dict
  • since the words are appended to the end of the file and I'd like them sorted alphabetically, the script then opens the file, switches to lines, removes any dupes with uniq, sorts alphabetically, then overwrites the file
  • checks the lists of added or not added words, and displays messages depending on whether a word was added or skipped, creating a git commit string and committing to git as needed
  • to create a list of words for the commit message, I thought I needed to use reduce and an accumulator, but it's more simple to use str join for that.

You can use a similar technique in nushell anytime you need to add strings to a file, whether they are words, commands, paths etc. Enjoy.

Thanks

  • @melMass - for the help in figuring out appending with a newline and the advice to separate it into a utility command, then for the proposal on how to improve the script. :)

image

...
# env vars
let-env LANG = 'ja_JP.UTF-8'
let-env EDITOR = 'code'
let-env GPG_TTY = (tty)
let-env DICT_FILE_PATH = '/Users/rcogley/dev/jpassgen/'
# let-env PRODB15331TOKEN = (open --raw "~/.ssh/tokens/PRODB15331TOKEN")
open ~/.ssh/tokens/api-tokens.nuon | load-env
...
# Add words to the dictionary file
def "dict add" [
...words: string
--dictpath (-p): string # assign a different path to dict file
] {
# Set working directory of dict file, default to envar
let dictpath = ($dictpath | default (get-dict-file-path))
# Set dict file
# /Users/rcogley/dev/jpassgen/jrc-japanese-words-and-phrases.txt
let dictfile = (get_dict_file $dictpath)
# Get num words
let numwords = ($words | length)
# Display what we are doing
print $"(ansi bg_white)(ansi green_bold)◼️◼️◼️ ADD WORDS TO DICT ◼️◼️◼️(ansi reset)"
print $"(ansi bg_blue) 🧐 Confirming ($numwords) new words:(ansi reset)\n(ansi bg_purple)($words)(ansi reset)"
print $"(ansi bg_blue) Add to:(ansi reset)"
print $dictfile
# Setup lists to collect words added or not
mut addedwords = []
mut notaddedwords = []
# Loop through supplied words and add to dict if not there
print $"(ansi bg_blue) 🧐 Checking words...(ansi reset)"
for $word in $words {
if (open $dictfile | str contains $word) {
$notaddedwords ++= $word
} else {
$word | append_file $dictfile
$addedwords ++= $word
}
}
# Sort and clean up dict file
sort_dict $dictfile
# Display message depending on what happened
let numaddedwords = ($addedwords | length)
let numnotaddedwords = ($notaddedwords | length)
if $addedwords == [] {
print $"(ansi bg_red) 😩 Skipping all of ($numnotaddedwords) words:(ansi reset)\n(ansi bg_purple)($notaddedwords)(ansi reset)"
} else if $notaddedwords == [] {
print $"(ansi bg_blue) 🤩 Committing all of ($numaddedwords) new words:(ansi reset)\n(ansi bg_purple)($addedwords)(ansi reset)"
dict_added_git_commit $dictpath $dictfile $addedwords $numaddedwords
} else {
print $"(ansi bg_blue) 🤩 Committing ($numaddedwords) new words:(ansi reset)\n(ansi bg_purple)($addedwords)(ansi reset)"
print $"(ansi bg_red) 😩 Skipping ($numnotaddedwords) words:(ansi reset)\n(ansi bg_purple)($notaddedwords)(ansi reset)"
dict_added_git_commit $dictpath $dictfile $addedwords $numaddedwords
}
}
#Get the dict file path envar or error out
def get-dict-file-path [] {
if not "DICT_FILE_PATH" in $env {
error make {msg: "DICT_FILE_PATH not set"}
exit 1
}
return $env.DICT_FILE_PATH
}
#Get the dict file
def get_dict_file [dictpath] {
$dictpath | path join $"jrc-japanese-words-and-phrases.txt"
}
#Sort the dict file, remove dupes, re-save
def sort_dict [filepth:string] {
open ($filepth) | lines | uniq | sort | save --force ($filepth)
}
#Append words to the dict file
def append_file [
dest: string
] {
$"($in)\n" | save --raw --append $dest
}
#Commit the added words to git
def dict_added_git_commit [
dictpath: string
dictfile: string
addedwords: list
numaddedwords: int
] {
let delimiter = (char space)
cd ($dictpath)
let firstword = ($addedwords | get 0)
let commitdetails = ($addedwords | str join $delimiter)
git add $dictfile
git commit -m $"Add ($numaddedwords) words including ($firstword)\n\n($commitdetails)"
git push origin master
}
...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment