Blog :: Unforswearing

varied and misc

20220903 Get Started with Fzf in Zsh


Have you ever navigated to a directory in your terminal and wanted to select a file or folder from a menu, rather than typing ls to print a list of contents? Or perhaps you would rather use a single command to present a list of git options for you to choose instead of having to search your command history for frequently used (but often forgotten) commands? If you have experienced these annoyances, or if you want a simple way to choose items from a menu, fzf is the tool for you.

In this article you will learn about fzf, the command-line fuzzy finder. You will also learn a few ways that fzf can improve your scripts.

Installing fzf

fzf can be installed by cloning the repository, using homebrew on MacOS, or by using the default package manager in your Linux system. For more information, see junegunn/fzf#installation.

Basic Usage

fzf can be used to generate a simple menu from a list of items. For example, you can use fzf to display a list of files for you to choose from. To do this you can pipe a list of items into fzf in your terminal by using the command below

find . -type f -maxdepth 1 | fzf

You can also use command substitution to open the selected file in your editor.

$EDITOR $(find . -type f -maxdepth 1 | fzf)

Now that you understand the basic use of fzf, you can use the tool for more interesting automations.

Use fzf with Git

Let's say you have a list of git commands that you use regularly but you want to speed up your git usage by choosing commands from a menu, rather than typing git –help to remember the name of the command you want to use. First, start by printing a list of your commands in your terminal.

# The "-e" option translates "\n" to a literal new line, required by fzf
echo -e "clone\ninit\nadd\ncommit\npush\n"

Once your list of commands is set, you can pipe this list to fzf to display them in a menu

echo -en "clone\ninit\nadd –all\ncommit\npush\n" | fzf

The command above will present your list of commands as a menu, allowing you to select a command via fzf. However, this does not actually run the git command. To use fzf for executing git commands, you can use the code below

git $(echo -en "clone\ninit\nadd –all\ncommit\npush\n" | fzf)

The above command will run the selected git command without any additional work on your part, simplifying your workflow and saving time.


In this article you learned about fzf, how to install fzf, and some basic usage examples you can apply to your workflow today. For more information about the fzf command-line fuzzy finder, visit the official fzf repository at

20211206 A Markup Language

title: The Markup Language
tags: markup, compiler, programming_language
date created: Monday, December 6th 2021, 3:48:40 pm
date modified: Wednesday, August 3rd 2022, 10:32:11 pm

A Markup Language

Name: ??

Goal: Create a somewhat restricted markup language with minimal formatting noise.

Lang: ???

Sources / Inspiration

Many of the ideas below were borrowed from other systems / markup languages.

  • AbstractML:
  • Markdown Extra:
  • Orgmode:
  • Pug:
  • Quaint:
  • Restructured Text:
  • Skriv:


  • Minimal markup to enhance readability
  • Outputs HTML
  • All markup should be explicit with no magic or hidden behavior
  • Only one method to achieve a particular formatting goal
  • Lightweight options to formatting params to save keystrokes
  • Formatting is a single character aside from enumerated items (headings, lists, etc)
  • New Lines denote the end of paragraphs and other elements. All other whitespace is ignored.
  • No Task or To Do support



% Comments run to the end of the line and are ignored during processing
  • No multiline comments


= h1
== h2
=== h3


  • New lines denote the end of a paragraph. Multiple consecutive new lines are ignored.


  • Three hyphens


  • Unordered lists
+ item 1
+ item 2
++ item 2.1
++ item 2.2
+++ item 2.2.1
  • Ordered lists
# item 1
# item 2
## item 2.1
## item 2.2
### item 2.2.1

Code / Monospace

  • Inline code and code blocks wrapped in two backticks
``const addTwo = (num) => num + 2``

Code Blocks

const addTwo = (num) => num + 2
addTwo(5) // 7

Text Formatting

  • \bold\* and |italic| can be nested together
  • all other formatting cannot be nested and must be used individually

Block Quotes

> this is text in a block quote
> each line in the block quote must be 
> prepended with the right bracket char (like markdown)
> otherwise the text is assumed to be paragraph


  • Or without title (autolink)



Linked Images


Advanced Usage

  • These things will be built later and as extensions to the main markup lang above.

Text Formatting



markup |= special formatting used when creating textual documentation


SSIMS := Silver Spring International Middle School


  • Footnotes must be added to the bottom of the document
A footnote|1 can be used like so
1: Here is some supplemental text about footnotes


  • Tables are like CSV with special identifiers for headings and rows. Columns are indicated with commas. Tables are not meant to display complex data or formatting.
=Cities,    Pop,    State=
+Balitmore, 600K,   Maryland+
+New York,  2.5M,   New York+

Front Matter

title: A Markup Language
author: Unforswearing
  • Lengthy front matter can be sourced from an external file:
title: Appendix
include: pub_data.yaml
% this document now contains all front matter located in pub_data.yaml

Specifying HTML

  • Any html tag can be used, however they are best used to denote non-ambiguous document structure.
  • Optional new lines and indentation can be added for readibility.
= This is a document that contains HTML tags
Below is an introduction using a specified <div> element
#div Hello, I am unforswearing and this text is in a div element
#p Here is an additional paragraph

Computed Values / Inline Variables

Highlighted Callout Boxes

  • green (correct, continue)
  • blue (neutral)
  • red (incorrect, stop)
  • yellow (warning, caution)


  • to include content from other files in the current doc

20200918 DSL Thoughts

General Thoughts about Creating a Langauge / DSL

see also: configuration language, command language, other non-turing complete langauges

A very simple language

  • really only a few things are needed to implement a programming language:
  • system: args, show (print/echo), input, exit
  • file i/o: read, write, close
  • math: nothing, or whatever is in the source language
  • control:
- if/then/else, repeat - repeat is the only loop structure - returns are explicit >> no curly braces. if and for commands should end with dn for "done"
  • data structure: functions, arrays/lists (and methods)
>> functionname = (arg1, arg2) -> arg1 + arg2 :: functions only have two args max >> list = 1, 2, "a", "b" :: there are no types, arrays can be anything
a less minimal list could be something like:
system commands: args, print/show, input/read, exit, execute, (others) math: basic infix expressions / equality / modulous / etc <<< implemented myself ?? control: if/then/else,, break, return, try/err, wait/sleep, loop data structures: array/list (and methods) , struct/object {} (and methods), function/func/fun/fn/int/ types: number, string, array, struct, function, etc
  • use: include a file as a library for the current script
- use adds functions from "libfile.lang" in the current global object
  • variables cannot be assigned to the output of "use"


  • exp: export a function to be used from a library file
..file lib.lang
fn printhello() show "hello" dn
..file script.lang

Interesting things from other languages

  • Cue is interesting as a whole
  • Dhall is similar to Cue but with functions (and other stuff)

From Gleam

It would be fun to implement some of the Open Formula spec


type conversion

  • classes have parameters attached that describe how a conversion should be handled

list.char - split text or file by character, eg. `{"a",,"l","i","s","t"} list.word - split text or file by word , eg. {"a", "list"} list.line - split text or file by line , eg. {"a list"}


file - method to save files to disk , eg. @conv({#text, file, "/path/file.txt"}

text to number and number to text

these operations only require two arguments:

@conv({#var, file, "/path/to/number.txt"})
@conv({#var, file, "/path/to/text.txt"})
..change type from number/file/list/text to text/list/file/number
..NOTE: conv will only accept a list as an argument!!
@conv({#var, type - list|number|text|file, #optional_argument})
..- there is no number or none types so they cannot be declared as classes like list, text, and file
..- file to text is not necessary since files are read by default
..  when declaring the file instance using `filename::file("/path/to/file.txt")`
.."file to list" and "text to list" splits the file or text by character, word, or lines
..text and file have the same properties so the operations will work exactly the same for both types
@conv({#var, list, list.char})
@conv({#var, list, list.word})
@conv({#var, list, list.line})
.."number to file" and "text to file" saves the var value into a new file 
.. at path specified in #optional_argument
@conv({#var, file, "/path/to/number.txt"})
@conv({#var, file, "/path/to/text.txt"})
..number to text conversions numeric characters to text strings
..the third item in the list argument will be discarded
@conv({#var, text})
..text to number convs numeric characters to text strings
..NOTE: there is no number type so it cannot be declared like list, text, and file
..the third item in the list argument will be discarded
@conv({#var, number})

20170918 Reading Files Without Cat

Reading A File Without cat

I have been trying to find ways to avoid useless use of cat#Uselessuseofcat) but could never come up with a method of reading a file that did not involve creating an entire for or while loop. This problem crossed my mind yesterday and, after a quick google search, I found a neat way to avoid this in a single small command:

# contents of 'hi.txt'
cat hi.txt

# reading hi.txt without 'cat'
echo $(<hi.txt)
hi hello ok
<p /> Unfortunately, the command does not preserve new lines but for those times when you only need to read from a single line file, this does the trick.

20161013 Lnks


My tool to get a list of links from Google Chrome has been updated more than a few times since the previous post, including the ability to save links to instapaper or pastebin, and an option to save the page(s) to pdf (via wkhtmltopdf). Here's the brand new full list of options:

-s to save the links to a file on the desktop
-c to copy the links to your clipboard
-v to print the links to stdout with leading text
-p to print the links to stdout
-i to save the link(s) to instapaper
-b to save the link(s) to
-w to save each url as a pdf (saves the page via 'wkhtmltopdf')
-h prints this help message
- lnks accepts one option. the program will fail if run with more than one option.
- using option -s will allow you to specify an output file, such as:
		lnks -s searchterm matchinglinks.txt

I spent a while trying to figure out what I want to do next with lnks and feel pretty good about what I have planned:

Use Safari Instead

Every now and again I take Safari out for a spin, and during one of those times I created surls to mimic lnks functionality. Merging surls with lnks makes a lot of sense, and got me thinking maybe I can add...

Canary, Chromium, and Webkit Support As Well

Most (if not all) of these browsers are scriptable via Applescript and it's gonna be great to brush up on my Applescripting. I am more than a bit out of practice.

Pinboard Support

I was super excited to add Instapaper support to lnks but got super bummed when I saw that they were sold to Pinterest. I probably won't drop Instapaper support for lnks (despite my silly threat), but I definitely want to add an alternative. Pinboard is a clean, well developed option I have on the horizon.


It'd be really great to not have to specify any new or old options every time lnks is run, so how about a configuration file? This will essentially be an expanded version of the current conf file that will be read at runtime.

There are a few other maintenance updates that I have planned for the far distant future, but I'm not quite there yet. Check back soon!

20130314 Video Processing


  1. Videos are exported from Camtasia/FCE/Etc
  2. Exports are saved directly to a Dropbox folder: /Dropbox/VideoProcessing/Originals
* Files in the Originals folder are immediately processed by FFMPEG/HandbrakeCLI
* Files in the Originals folder that are 1 week old are sent to permanent storage
  1. Processed files are sent to the Exports folder: /Dropbox/VideoProcessing/Exports
  2. The exports folder will be "watched" by Hazel
* A script will alert me to new files, or
* The file will automatically be moved to a folder on my desktop


  1. Video sizes are often more than 2 GB
* Personal account is too small
* Training account will put files on Jons computer
* Work account will work for anything under 2 GB
* Sub with Google Drive (up to 40 GB)?
  1. There may be issues with the script running prematurely
* Script did not wait until the video fully processed. 
* That issue might be specific to applescript/hazel?

                    |   +---------+    |       |     +----------------+
                    |                  |       |     |FFMPEG/HANDBRAKE+-----------+
                    |                  |       |     +----------------+           |
                    |raw exp           |       |         ^                        |
+------+            |                  |       |         |                        |
|      | raw exp +-------------+       |       v         |                        |
|      +-------->|             |       |     +-----------+---+                    |
| MAC  |         |   DROPBOX   |       |     | Processing PC |                    |
|      |<--------+             |       |     +---------------+                    |
|      | pross'd +-------------+       |                                          |
+------+            ^                  |                                          |
                    |                  |                                          |
                    |                  |                                          |
                    |                  |                                          |
                    |processed         |after 1 wk +--> +---------------------+   |
                    |                  +--------------->|Raw/Originals Storage|   |
                    |    +-------+                      +---------------------+   |
                    +----+Exports|                                                |
                         +-------+                                                |
                             ^                                                    |
                             |                                                    |
                             |          <--------+compressed files                |




20120820 Navi Note Language

Navi Note Processing Language

Navi is a simple way to take and process notes. Take notes using the simple Navi syntax and when you need a review of the important tasks, low priority tasks, comments, and contexts, run it through the Navi processor.

  • All notes, questions, high priority, and comments fit under a context heading as a project
  • There is no whitespace within the project. Whitespace delimits each project
  • All tasks/items begin with a signifier (-,>,∆,etc)
  • Completed tasks/items have x placed before their signifier (x-,x>,x∆,etc)


	- Normal priority/unprioritized task/item/comment/note
	> High priority task/item
	∆ Backburner task/item (alt+j)
	† Waiting for something before continuing (alt+t)
	x Completed task/item
	? Question about a task/project
	! Important comment about a task/project
$$ end of project


sed -n '/@Project/ ,/$$/'
	grep '>' (etc)

201201216 Ivan Markup Language

Ivan Markup Language


The goal is to be fast and simple, without having to remember formatting rules. When run through the parser, all Ivan Markup is compiled into HTML, which can then be optionally converted to pdf via wkhtmltopdf. Ivan is built entirely with Ruby and Sed.

I built Ivan to suit my needs, and so it doesn't have a lot of the capabilities of other "lightweight markup languages." Specifically:

  • No support for tables, since I never use them
  • No support for code blocks, but this may change
  • Only the <h1> and <h2> header options
  • No relative links, inline anchors, cross references.

Since this was a test of my limited programming capabilities, the syntax rules are pretty strict

  • no spaces between the formatting characters and the words you are applying the formatting to. E.G. :bold words: works but : bold words : will not.
- list item - 
- list item - 
  - nested list item - 
  - nested list item - 

Possible later additions:

+;my email+;;+
code block

Code structure

To start, write functions for each conversion that is needed: 1. h1 2. h2 3. bold 4. italic 5. underline 6. links w/o alt text 7. links w/ alt text 8. email w/o alt text 9. email w/ alt text 10. inline code


Read file DOCUMENT
  WORDS = words of DOCUMENT
  if WORDS contains (markup syntax 1) 
    do FUNCTION 1
  elsif WORDS contains (markup syntax 2) 
    do FUNCTION 2
(etc through 10 functions
  when “-o” 
    save as newname.html
  when “-f”
    save as name.pdf,md
  when “-o” 
    save as newname.html
  when “-f”
    save as name.pdf,md


The parser will read each line and then each word of the file, compare it to each of the 10 functions using ‘if’ statements in a ‘for’ loop. If it matches one, the function containing the code will process the word. If it doesn’t match any, it will continue to loop through the words in the file until there are no more words.

Ivan parser will exist as a command line only (because this has no place in Applescript). The script will take one file as an argument and convert to HTML by default. I am undecided about accepting processing options, but some ideas would be to

  • ivan foo.txt (html only)
  • ivan foo.txt -o bar.html (specify output filename — HOW?)
  • ivan foo.txt -f pdf,md (convert a doc to pdf or markdown, maybe rtf)
  • ivan foo.txt -f pdf,md -o bar.pdf,md (like above, with a new filename

The internal Ivan parsing will be written by me. The pdf and md formats will happen via ‘wkhtmltopdf’ (ruby) and ‘pandoc’ respectively.


  • Make sure the script doesn't endlessly iterate
- Possibly use the ‘++’ option to stop the script from starting at the beginning
  • Make sure the script can handle any punctuation
  • Make sure the script can process the words regardless where they are placed in the string.
  • Keep the formatting strict to avoid stupid errors


# Sed
## bold: 
sed 's/ :/ <bold>/g' | sed 's/: /<\/bold> /g' |  sed 's/^:/ <bold>/g' | sed 's/:$/<\/bold> /g' | sed 's/:./<\/bold>/'
## paragraph breaks:
sed 's/^/<p>/' | sed 's/$/<\/p>/'
# Awk
## get alt text for link
awk -F+ '{ print $1 }' | sed 's/{//'