Unicode Progress Bars using TextExpander

Unicode Progress Bars using TextExpander

Rationale

When I'm using Roam I frequently create progress bars using a unicode progress bar generator (1). One problem I frequently run into is having to open the website and having to configure the tool over and over again.

  • Ideally I'd want a one step solution where I can enter a command on the command line
  • Alternatively I could also use a TextExpander

Requirements

Should be able to handle input 40 as ⣿⣿⣿⣿⣀⣀⣀⣀⣀⣀ 40%
Should be able to handle input 2/5 as ⣿⣿⣿⣿⣀⣀⣀⣀⣀⣀ 40%

Method

  1. Install TextExpander
    • Signup
  2. Create a New Snipper
    • Give it name Progress Bar
    • Give it an abbreviation jjbar
  3. Fill in the following code
// Capture incoming 
var toParse = %filltext:name=Enter Percentage:default=0%;

// Adjust percentage if division occurs
if ("".indexOf.call(toParse, "/")) {
  toParse = toParse + " * 100"
}

// Excerpt (Copied & Improvised from Changaco(1)) - See Below
var bar_styles = ['⣀⣄⣤⣦⣶⣷⣿'];

// Helper Function
function repeat(s, i) {
    var r = '';
    for(var j=0; j<i; j++) r += s;
    return r;
}

// Makes the bar
function make_bar(p, bar_style, min_size, max_size) {
    var d, full, m, middle, r, rest, x,
        min_delta = Number.POSITIVE_INFINITY,
        full_symbol = bar_style[bar_style.length-1],
        n = bar_style.length - 1;
    if(p == 100) return {str: repeat(full_symbol, 10), delta: 0};
    p = p / 100;
    for(var i=max_size; i>=min_size; i--) {
        x = p * i;
        full = Math.floor(x);
        rest = x - full;
        middle = Math.floor(rest * n);
        if(p != 0 && full == 0 && middle == 0) middle = 1;
        d = Math.abs(p - (full+middle/n)/i) * 100;
        if(d < min_delta) {
            min_delta = d;
            m = bar_style[middle];
            if(full == i) m = '';
            r = repeat(full_symbol, full) + m + repeat(bar_style[0], i-full-1);
        }
    }
    return {str: r, delta: min_delta};
}

function parse(str) {
  return Function(`'use strict'; return (${str})`)()
}

// Generates the bar
function generate(p) {
    var min_size = 10;
    var max_size = 10;
    var bars = [];
    for(var i=0; i<bar_styles.length; i++) {
        bars.push(make_bar(p, bar_styles[i], min_size, max_size));
    }
    bars.sort(function (a, b) { return a.delta - b.delta; });
    for(var i=0; i<bars.length; i++) {
        bar = bars[i].str+' '+p;
        delta = bars[i].delta.toPrecision(2);

    }
    return bar;
}

// Parses the incoming expression (to evaluate if necessary)
function generateParse(toParse) {
    return generate(Math.round(parse(toParse)))
}

// Snippet that returns the result | e.g. ⣿⣿⣿⣿⣄⣀⣀⣀⣀⣀ 42%
"" + generateParse(toParse) + "%";

Possible Next Steps

Explore whether Text Expanders can do this
Explore whether this should be turned into an NPM script

Reference

  1. Unicode Progress Bar - Generator
  2. Unicode Progress Bar - Changaco @ Github

Example of
Example of
Create
Create