jisifu

Mataroa nushell cli aliases powered

Very quick CLI development with nushell

Using scripting with nushell, one can make an interactive prompt with gum and piping to get posts straight to the terminal. Here is the script so far and I'm looking to add some more features to make a complete suite of cli commands purely in nu:

let token = sops -d ~/nixconfig/modules/secrets/apikeys.yaml
  | from yaml
  | get MATAROA.BEARER.TOKEN
let url = "https://mataroa.blog/api/posts/"

export def mget [] {
let slug =  http get -H ["Authorization" $"Bearer ($token)"] ($url)
    | get post_list.slug
    | to text
    | gum choose
  
  http get -H ["Authorization" $"Bearer ($token)"] ($url)($slug)/
}

export def mpost [] {
  let title = gum input
  let body = gum write

  {title: ($title) body: ($body)}
  | to json
  | http post -H ["Authorization" $"Bearer ($token)"] ($url)
}

Note, because nushell is rather new, I don't think the current markdownlinter recognizes the syntax highlighting so I am using javascript instead just for the perks of readability

At the time of writing and editing this, I have already implemented the following refactoring of the script to allow for edits to the post with a full fetch of the published draft as a value for the editing process. This is one of those complex abstractions of taking away the PATCH function and giving the user a more streamlined "edit" flavor. Ultimately, it's just a tiny UX improvement.

let token = sops -d ~/nixconfig/modules/secrets/apikeys.yaml
  | from yaml
  | get MATAROA.BEARER.TOKEN
let url = "https://mataroa.blog/api/posts/"
let blob = http get -H ["Authorization" $"Bearer ($token)"] ($url)
let slug =  ($blob)
    | get post_list.slug
    | to text

export def mget [] {
  http get -H ["Authorization" $"Bearer ($token)"] ($url)($slug|gum choose)/
}

export def mpost [] {
  let title = gum input
  let body = gum write

  {title: ($title) body: ($body)}
  | to json
  | http post -H ["Authorization" $"Bearer ($token)"] ($url)
}

export def mpublish [] {
  let title = gum input
  let body = gum write
  let publish = date now | format date "%Y-%m-%d"

  {title: ($title) body: ($body) published_at: ($publish)}
  | to json
  | http post -H ["Authorization" $"Bearer ($token)"] ($url)
}
export def medit [] {
  let choice = $slug|gum choose
  let selection = ($blob).post_list | where slug == ($choice)
  let title = gum input --value ($selection | get title | to text)
  let body = gum write --value ($selection | get body | to text)
  {title: ($title) body: ($body) }
  | to json
  | http patch -H ["Authorization" $"Bearer ($token)"] ($url)($choice)/
}

This is a pretty big refactoring but I the end result is that once you source this .nu script, you get the aliases mget, mpost, mpublish, and medit to use in your nushell prompt. Whereby, the mget and medit commands interactively provides a menu of published posts/drafts and with a selection gives you the post contents and the interactive gum edits via the GUM CLI scripts. Really interesting interaction and I think a key take-away for someone implementing this on their own is to make sure the interactive gum doesn't load outside of the function definitions or else it will prompt it upon sourcing the nu file. This might be something I can take advantage of for environment setups that do need this initialization or instantiation phase prior to engaging with the program's control loops. Authentication for example is an obvious example where this is relevant. This might be something I can try to implement in a future post but this has been an interesting and fun one-day project.

Thoughts? Leave a comment