diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..4947545 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +FROM ruby:3.4 + +# Set the working directory +WORKDIR /site + +# Copy the site files +COPY blog /site + +# Install site dependencies +RUN bundle install + +# Build the site +RUN bundle exec jekyll build + +# Copy the built site to a separate directory +RUN mkdir /output && cp -r _site/* /output/ + +# Expose Jekyll default port +EXPOSE 4000 + +# Serve the site +CMD ["bundle", "exec", "jekyll", "serve", "--host", "0.0.0.0", "--watch", "--drafts"] diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index a643e9f..0000000 --- a/Gemfile.lock +++ /dev/null @@ -1,74 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - addressable (2.5.2) - public_suffix (>= 2.0.2, < 4.0) - colorator (1.1.0) - concurrent-ruby (1.1.4) - em-websocket (0.5.1) - eventmachine (>= 0.12.9) - http_parser.rb (~> 0.6.0) - eventmachine (1.2.7) - ffi (1.9.25) - forwardable-extended (2.6.0) - http_parser.rb (0.6.0) - i18n (0.9.5) - concurrent-ruby (~> 1.0) - jekyll (3.8.5) - addressable (~> 2.4) - colorator (~> 1.0) - em-websocket (~> 0.5) - i18n (~> 0.7) - jekyll-sass-converter (~> 1.0) - jekyll-watch (~> 2.0) - kramdown (~> 1.14) - liquid (~> 4.0) - mercenary (~> 0.3.3) - pathutil (~> 0.9) - rouge (>= 1.7, < 4) - safe_yaml (~> 1.0) - jekyll-feed (0.11.0) - jekyll (~> 3.3) - jekyll-sass-converter (1.5.2) - sass (~> 3.4) - jekyll-seo-tag (2.5.0) - jekyll (~> 3.3) - jekyll-watch (2.1.2) - listen (~> 3.0) - kramdown (1.17.0) - liquid (4.0.1) - listen (3.1.5) - rb-fsevent (~> 0.9, >= 0.9.4) - rb-inotify (~> 0.9, >= 0.9.7) - ruby_dep (~> 1.2) - mercenary (0.3.6) - minima (2.5.0) - jekyll (~> 3.5) - jekyll-feed (~> 0.9) - jekyll-seo-tag (~> 2.1) - pathutil (0.16.2) - forwardable-extended (~> 2.6) - public_suffix (3.0.3) - rb-fsevent (0.10.3) - rb-inotify (0.10.0) - ffi (~> 1.0) - rouge (3.3.0) - ruby_dep (1.5.0) - safe_yaml (1.0.4) - sass (3.7.2) - sass-listen (~> 4.0.0) - sass-listen (4.0.0) - rb-fsevent (~> 0.9, >= 0.9.4) - rb-inotify (~> 0.9, >= 0.9.7) - -PLATFORMS - ruby - -DEPENDENCIES - jekyll (~> 3.8.5) - jekyll-feed (~> 0.6) - minima (~> 2.0) - tzinfo-data - -BUNDLED WITH - 1.17.2 diff --git a/_posts/2025-2-2-blah.markdown b/_posts/2025-2-2-blah.markdown deleted file mode 100644 index fc5909f..0000000 --- a/_posts/2025-2-2-blah.markdown +++ /dev/null @@ -1,8 +0,0 @@ ---- -layout: post -title: "Hope this works" -date: 2025-02-08T18:04:18.692Z -categories: utilities ---- - -Blah blah blah blah diff --git a/.gitignore b/blog/.gitignore similarity index 100% rename from .gitignore rename to blog/.gitignore diff --git a/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Cache/b7/9606fb3afea5bd1609ed40b622142f1c98125abcfe89a76a661b0e8e343910 b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Cache/b7/9606fb3afea5bd1609ed40b622142f1c98125abcfe89a76a661b0e8e343910 new file mode 100644 index 0000000..7691ece --- /dev/null +++ b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Cache/b7/9606fb3afea5bd1609ed40b622142f1c98125abcfe89a76a661b0e8e343910 @@ -0,0 +1 @@ +I" {"title" => "🌲 johncsimon.github.io 🐦", "author" => "Abhinav Saxena", "url" => "http://0.0.0.0:4000", "description" => "got some downtime so how's about we starts ourselves a blog ...", "favicon" => "./logo.png", "remote_theme" => "abhinavs/moonwalk", "theme_config" => {"appearance" => "dark", "back_home_text" => "home..", "date_format" => "%Y-%m-%d", "show_description" => true, "show_navbar" => true, "show_footer" => true, "show_projects" => true, "show_old_projects" => true, "show_misc_list" => false}, "sass" => {"style" => :compressed}, "source" => "/site", "destination" => "/site/_site", "collections_dir" => "", "cache_dir" => ".jekyll-cache", "plugins_dir" => "_plugins", "layouts_dir" => "_layouts", "data_dir" => "_data", "includes_dir" => "_includes", "collections" => {"posts" => {"output" => true, "permalink" => "/:categories/:year/:month/:day/:title:output_ext"}}, "safe" => false, "include" => [".htaccess"], "exclude" => [".sass-cache", ".jekyll-cache", "gemfiles", "Gemfile", "Gemfile.lock", "node_modules", "vendor/bundle/", "vendor/cache/", "vendor/gems/", "vendor/ruby/"], "keep_files" => [".git", ".svn"], "encoding" => "utf-8", "markdown_ext" => "markdown,mkdown,mkdn,mkd,md", "strict_front_matter" => false, "show_drafts" => true, "limit_posts" => 0, "future" => false, "unpublished" => false, "whitelist" => [], "plugins" => ["jekyll-feed"], "markdown" => "kramdown", "highlighter" => "rouge", "lsi" => false, "excerpt_separator" => "\n\n", "incremental" => false, "detach" => false, "port" => "4000", "host" => "0.0.0.0", "baseurl" => nil, "show_dir_listing" => false, "permalink" => "date", "paginate_path" => "/page:num", "timezone" => nil, "quiet" => false, "verbose" => false, "defaults" => [], "liquid" => {"error_mode" => "warn", "strict_filters" => false, "strict_variables" => false}, "kramdown" => {"auto_ids" => true, "toc_levels" => [1, 2, 3, 4, 5, 6], "entity_output" => "as_char", "smart_quotes" => "lsquo,rsquo,ldquo,rdquo", "input" => "GFM", "hard_wrap" => false, "guess_lang" => true, "footnote_nr" => 1, "show_warnings" => false, "syntax_highlighter" => "rouge", "syntax_highlighter_opts" => {default_lang: "plaintext", guess_lang: true}, "coderay" => {}}, "github_username" => "johncsimon", "theme" => "moonwalk", "watch" => true, "livereload_port" => 35729, "serving" => true}:ET \ No newline at end of file diff --git a/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/06/753e995b3c003834d56acad82fff6bf9825fdbd0513298290d61eb63dff9e8 b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/06/753e995b3c003834d56acad82fff6bf9825fdbd0513298290d61eb63dff9e8 new file mode 100644 index 0000000..4defdad --- /dev/null +++ b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/06/753e995b3c003834d56acad82fff6bf9825fdbd0513298290d61eb63dff9e8 @@ -0,0 +1,3 @@ +I"K

I’m currently reading a contemporary history of Steve Jobs’s time with the creation and unraveling of NeXT Computer - Steve Jobs and the NeXT Big Thing. +Steve Jobs and the NeXT Big Thing

+:ET \ No newline at end of file diff --git a/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/25/4f73d86242e65a8772b6e9724619aab1da63b1df869f2f3b8c9464dbd9b611 b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/25/4f73d86242e65a8772b6e9724619aab1da63b1df869f2f3b8c9464dbd9b611 new file mode 100644 index 0000000..5245025 --- /dev/null +++ b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/25/4f73d86242e65a8772b6e9724619aab1da63b1df869f2f3b8c9464dbd9b611 @@ -0,0 +1,2 @@ +I"N

got some downtime so how’s about we starts ourselves a blog …

+:ET \ No newline at end of file diff --git a/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/28/409282bc7b120130c52502bbf529c1f4888a953e7404ed794fc89f19ad0b40 b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/28/409282bc7b120130c52502bbf529c1f4888a953e7404ed794fc89f19ad0b40 new file mode 100644 index 0000000..ea85f17 --- /dev/null +++ b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/28/409282bc7b120130c52502bbf529c1f4888a953e7404ed794fc89f19ad0b40 @@ -0,0 +1,2 @@ +I"†

I’m a software dev with Go, Javascript and C#. I’m writing this blog to better at writing and to document my explorations.

+:ET \ No newline at end of file diff --git a/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/39/10527bad802f5b463cf43eff4825977cf595078493d02f3cbf7409f0098e86 b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/39/10527bad802f5b463cf43eff4825977cf595078493d02f3cbf7409f0098e86 new file mode 100644 index 0000000..d225893 --- /dev/null +++ b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/39/10527bad802f5b463cf43eff4825977cf595078493d02f3cbf7409f0098e86 @@ -0,0 +1,222 @@ +I"b.

I like to play around with lots of different programming languages, but install too many and they pollute your working environment, so it’s better to have them installed as a user instead of root. +Here’s a way to get several of them installed into your unix user directory. +If things go wrong, or you get bored you can easily rm -rf the installation.

+ +

Initial Install

+

Let’s get ourselves a minimal debian environment. I’m using docker here, but you can use a native install, or a VM, or Windows Services for Linux with the ubuntu install.

+
john@BigBox:~/git/JohnCSimon.github.io$  sudo docker run -ti debian /bin/bash
+Unable to find image 'debian:latest' locally
+latest: Pulling from library/debian
+cd8eada9c7bb: Pull complete
+Digest: sha256:58a80e0b6aa4d960ee2a5452b0230c406c47ed30a66555ba753c8e1710a434f5
+Status: Downloaded newer image for debian:latest
+root@6d933dddbbcd:/#
+
+

Just to satisfy my OCD let’s get the latest updates.

+ +

apt update && apt upgrade -y

+ +

apt install gnupg2 curl procps -y + Installs gpg2, curl and ps

+ +

ruby

+

gpg2 --keyserver hkp://pool.sks-keyservers.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB

+ +

\curl -sSL https://get.rvm.io | bash -s stable

+ +

To start using RVM you need to run source /etc/profile.d/rvm.sh or re-login to re-load ~/.profile

+ +

From here you can run - rvm list known and you’ll see a list of ruby flavors and individual versions.

+ +
# MRI Rubies
+[ruby-]1.8.6[-p420]
+[ruby-]1.8.7[-head] # security released on head
+[ruby-]1.9.1[-p431]
+[ruby-]1.9.2[-p330]
+[ruby-]1.9.3[-p551]
+[ruby-]2.0.0[-p648]
+[ruby-]2.1[.10]
+[ruby-]2.2[.10]
+[ruby-]2.3[.8]
+[ruby-]2.4[.5]
+[ruby-]2.5[.3]
+[ruby-]2.6[.0]
+
+ +

MRI Ruby is the reference version of Ruby so let’s install the latest version.

+ +

rvm install ruby-2.6.0

+ +

I’m running debian and rvm might ask for your root password to install some prerequsites from apt before compiling a new version.

+ +

Congrats, you now have a ruby install

+ +
$ ruby -v
+ruby 2.6.0p0 (2018-12-25 revision 66547) [x86_64-linux]
+
+ +

from here you can now do whatever since I’m blogging this using jekyll

+ +

gem install bundler jekyll

+ +

go

+

Go is a language that releases new versions on a regular basis. +There’s a similar tool to rvm called gvm. It’s a ā€œgo version managerā€ available from here https://github.com/moovweb/gvm that’ll let you install multiple versions and set $GOPATH and $GOROOT.

+ +

as a regular user:

+
$ bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
+Cloning from https://github.com/moovweb/gvm.git to /root/.gvm
+No existing Go versions detected
+Installed GVM v1.0.22
+
+Please restart your terminal session or to get started right away run
+ `source /root/.gvm/scripts/gvm`
+
+ +

you should be able to run and see

+
$ gvm version
+Go Version Manager v1.0.22 installed at /home/john/.gvm
+
+ +

Run gvm listall +which will give you a list of all the available versions of go.

+ +
$gvm listall
+
+gvm gos (available)
+
+   go1
+   go1.0.1
+   ...
+   go1.11rc1
+   go1.11rc2
+   go1.11.1
+   go1.11.2
+   go1.11.3
+   go1.11.4
+   go1.12beta1
+   go1.12beta2
+
+

of which there are entirely too many.

+ +

From here, we can install go as our user via binary here:

+ +

gvm install go1.4 -B

+ +

try it out

+
$ go version
+go version go1.4 linux/amd64
+
+

We can see it gets installed here:

+
$ echo $GOROOT
+/home/john/.gvm/gos/go1.4
+
+ +

From the gvm link earlier, in order to compile a go build environment for versions 1.5 on we require another go build environment. +Go compiles itself! Neat huh?

+ +

As of now the latest version is go1.11.4

+
$ export GOROOT_BOOTSTRAP=$GOROOT
+$ gvm install go1.11.4
+
+ +
$ go version
+go version go1.4 linux/amd64
+
+

you can run +gvm use - select a go version to use (--default to set permanently)

+ +
$ gvm use go1.11.4 --default
+Now using version go1.11.4
+$ go version
+go version go1.11.4 linux/amd64
+$ echo $GOROOT
+/home/john/.gvm/gos/go1.11.4
+$ echo $GOPATH
+/home/john/.gvm/pkgsets/go1.11.4/global
+$ ls /home/john/.gvm/gos/go1.11.4
+AUTHORS  CONTRIBUTING.md  CONTRIBUTORS  LICENSE  PATENTS  README.md  VERSION  api  bin  doc  favicon.ico  lib  manifest  misc  pkg  robots.txt  src  test
+ls $GOPATH
+overlay  pkg  src
+
+ +

Be sure to set –default so you keep the same version when you relaunch the shell, so that whatever you install stays where you expect it.

+ +

node js

+

node.js, the server side javascript framework

+ +

nvm is Node Version Manager. Install it like this: +curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash

+ +

Since there are major revisions to the javascript language between node 4, 6, 8 I’ve found I’ve had to switch more often between these versions according to project than I did with other languages.

+ +

You can run nvm ls-remote and get a list of all the node versions available

+ +
$ nvm
+Example:
+  nvm install 8.0.0                     Install a specific version number
+  nvm use 8.0                           Use the latest available 8.0.x release
+  nvm run 6.10.3 app.js                 Run app.js using node 6.10.3
+  nvm exec 4.8.3 node app.js            Run `node app.js` with the PATH pointing to node 4.8.3
+  nvm alias default 8.1.0               Set default node version on a shell
+  nvm alias default node                Always default to the latest available node version on a shell
+
+ +

so if you run

+ +
$ nvm install 10
+Downloading and installing node v10.15.0...
+Downloading https://nodejs.org/dist/v10.15.0/node-v10.15.0-linux-x64.tar.gz...
+######################################################################## 100.0%
+Computing checksum with sha256sum
+Checksums matched!
+Now using node v10.15.0 (npm v6.4.1)
+Creating default alias: default -> 10 (-> v10.15.0)
+
+$ whereis node
+node: /home/john/.nvm/versions/node/v10.15.0/bin/node
+
+ +

and you can set it to be the default so the setting persists between sessions

+
nvm alias default 10
+
+ +

So now you can run:

+
$ node -v
+v10.15.0
+$ npm -v
+6.4.1
+
+ +

rust

+

Rust is another language that sees regular updates. You’ll just have to check which is the version for the 2015 and 2018 edition.

+ +
curl https://sh.rustup.rs -sSf | sh
+
+
+
+Current installation options:
+
+   default host triple: x86_64-unknown-linux-gnu
+     default toolchain: stable
+  modify PATH variable: yes
+
+1) Proceed with installation (default)
+2) Customize installation
+3) Cancel installation
+>
+
+select 1 
+
+To configure your current shell run source $HOME/.cargo/env
+
+ +

add $HOME/.cargo/env to your path in .bashrc

+ +
$ whereis cargo
+cargo: /home/john/.cargo/bin/cargo
+$ whereis rustc
+cargo: /home/john/.cargo/bin/rustc
+
+ +:ET \ No newline at end of file diff --git a/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/3b/7acab97e28d6e6622b24af72b2520376a93d9dbb3d6cdf57d927a166fb4c2f b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/3b/7acab97e28d6e6622b24af72b2520376a93d9dbb3d6cdf57d927a166fb4c2f new file mode 100644 index 0000000..b368357 --- /dev/null +++ b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/3b/7acab97e28d6e6622b24af72b2520376a93d9dbb3d6cdf57d927a166fb4c2f @@ -0,0 +1,4 @@ +I"¦

I like to play around with lots of different programming languages, but install too many and they pollute your working environment, so it’s better to have them installed as a user instead of root. +Here’s a way to get several of them installed into your unix user directory. +If things go wrong, or you get bored you can easily rm -rf the installation.

+:ET \ No newline at end of file diff --git a/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/48/3bf5d010bfcbf2c17a7d5fcaa24b376f795bc6c7c4dce95d7424349e10f11e b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/48/3bf5d010bfcbf2c17a7d5fcaa24b376f795bc6c7c4dce95d7424349e10f11e new file mode 100644 index 0000000..dee9687 --- /dev/null +++ b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/48/3bf5d010bfcbf2c17a7d5fcaa24b376f795bc6c7c4dce95d7424349e10f11e @@ -0,0 +1,2 @@ +I"H

Recently I had to write a file uploader for AWS S3 in node.

+:ET \ No newline at end of file diff --git a/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/69/5f773373ce5344de744369cb7f5a8494d0c68bc72c923ef1102e0b9ce4d1c1 b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/69/5f773373ce5344de744369cb7f5a8494d0c68bc72c923ef1102e0b9ce4d1c1 new file mode 100644 index 0000000..4c0fac0 --- /dev/null +++ b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/69/5f773373ce5344de744369cb7f5a8494d0c68bc72c923ef1102e0b9ce4d1c1 @@ -0,0 +1,2 @@ +I"*

Poor Man’s Audiobook Reader

+:ET \ No newline at end of file diff --git a/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/8f/7e04095acc834652ced033ae7791a9c0cfcf14e4976bf40f5b7e2178e44b59 b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/8f/7e04095acc834652ced033ae7791a9c0cfcf14e4976bf40f5b7e2178e44b59 new file mode 100644 index 0000000..dee9687 --- /dev/null +++ b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/8f/7e04095acc834652ced033ae7791a9c0cfcf14e4976bf40f5b7e2178e44b59 @@ -0,0 +1,2 @@ +I"H

Recently I had to write a file uploader for AWS S3 in node.

+:ET \ No newline at end of file diff --git a/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/97/67915f405b1b58b7e972bfa6bec1f96439cfb21dd68bbc76541b7a9fac8d63 b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/97/67915f405b1b58b7e972bfa6bec1f96439cfb21dd68bbc76541b7a9fac8d63 new file mode 100644 index 0000000..82caec6 --- /dev/null +++ b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/97/67915f405b1b58b7e972bfa6bec1f96439cfb21dd68bbc76541b7a9fac8d63 @@ -0,0 +1,2 @@ +I"7

Gradual Typing With Javascript and VS Code

+:ET \ No newline at end of file diff --git a/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/d2/fbf109d853a7b2aac66de57c644bb3057ef9a956dc7e7634ff6e32e499e9d0 b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/d2/fbf109d853a7b2aac66de57c644bb3057ef9a956dc7e7634ff6e32e499e9d0 new file mode 100644 index 0000000..4defdad --- /dev/null +++ b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/d2/fbf109d853a7b2aac66de57c644bb3057ef9a956dc7e7634ff6e32e499e9d0 @@ -0,0 +1,3 @@ +I"K

I’m currently reading a contemporary history of Steve Jobs’s time with the creation and unraveling of NeXT Computer - Steve Jobs and the NeXT Big Thing. +Steve Jobs and the NeXT Big Thing

+:ET \ No newline at end of file diff --git a/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/d5/a5d4c8932742435b43783e6315f70f0e557f161b4d49ec8365a1c7f8a68661 b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/d5/a5d4c8932742435b43783e6315f70f0e557f161b4d49ec8365a1c7f8a68661 new file mode 100644 index 0000000..fd549fd --- /dev/null +++ b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/d5/a5d4c8932742435b43783e6315f70f0e557f161b4d49ec8365a1c7f8a68661 @@ -0,0 +1,2 @@ +I"+

🌲 johncsimon.github.io 🐦

+:ET \ No newline at end of file diff --git a/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/e3/b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/e3/b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 new file mode 100644 index 0000000..e135808 --- /dev/null +++ b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/e3/b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 @@ -0,0 +1,2 @@ +I" +:EF \ No newline at end of file diff --git a/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/ef/bc911949b3cd2c7638dc17ec49f5fa64632c0990bc22f096921658cf0600c9 b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/ef/bc911949b3cd2c7638dc17ec49f5fa64632c0990bc22f096921658cf0600c9 new file mode 100644 index 0000000..3c55e76 --- /dev/null +++ b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/ef/bc911949b3cd2c7638dc17ec49f5fa64632c0990bc22f096921658cf0600c9 @@ -0,0 +1,63 @@ +I"s

I’m currently reading a contemporary history of Steve Jobs’s time with the creation and unraveling of NeXT Computer - Steve Jobs and the NeXT Big Thing. +Steve Jobs and the NeXT Big Thing

+ +

Today, popular culture paints him as an iconic figure, but when the book was written in 1993 NeXT was a money pit, only kept alive with cash infusions from outside investors as money was burnt. It’s a wild ride, I highly recommend it, especially with hindsight.

+ +

Unfortunately, reading books cover to cover is hard for me. I rely on audiobooks so I can ride the bus or do dishes while I absorb a book. Unfortunately, there is no audiobook release of this book.

+ +

I found the book in PDF form on archive.org. Unfortunately PDFs are more of a page layout language like HTML instead of a store of text.

+ +

If you were to use Text to Speech functionality say - speak visible content on your PC or phone on a typical website or PDF you have to ā€˜baby sit’ what is being read so that the reader doesn’t get ā€˜lost’ or get caught up on footnotes or stop abruptly or be unable to handle a change in fonts. It’s not obvious how broken this functionality is.

+ +

Speak Visible Content

+ +

Plain text is the best for a text to speech program. Luckily, archive.org provides a plain text version of the book which was created via optical character recognition (see the archive.org site). Short of a few footnotes, it’s 95% of what we need.

+ +

Except… text to speech generation is a high CPU task, Apple iOS doesn’t like long running tasks. You can’t scrub back and forth within a document like you can with an audio book or video. Also, it seems that this functionality within iOS doesn’t see as much development as other parts of the OS, it’s generally a janky experience more optimized for the vision impaired than my use case.

+ +

So, we need an offline bulk text to speech generator. Luckily, macOS provides just the very thing hidden as one of the command line utilities - this is the say utility say -v Bad\ News "Captain, you are needed on the bridge" -w 200 but it can take additional parameters (see the man pages ā€œman sayā€ )

+ +

example call:

+ +
say --voice=Ava \ # use '?' to get a list of all the available voices
+    --input-file Steve_Jobs_\&_the_NeXT_Big_Thing_1993_djvu.txt \ # path to plain text file
+    --data-format=m4b \ # File for the output format, m4b is the apple's audiobook equavalent of m4a see 'say --file-format='?' ' for the list of these
+    --output-file=MyOutputFile.m4b \ # output file
+    --rate=150 # speaking rate in words per minute, to your taste.
+    --progress # print the progress
+
+ +

This is awesome! But after letting it run for one later the CPU is still at 100% and the process is consuming 2.3 GB of RAM and the output file MyOutoutFile.m4b is about 50 MB on disk.

+ +

Something is up … let’s see the word count of this file.

+ +
wc -lw Steve_Jobs_\&_the_NeXT_Big_Thing_1993_djvu.txt
+14908  122808 Steve_Jobs_&_the_NeXT_Big_Thing_1993_djvu.txt
+
+ +

so 15000 lines, 122000 words - at 150 words / minute this is about 13 hours to read through all of it, and an audiobook of that length is roughly 1 GB.

+ +

Maybe the compression or some other non-default setting is mucking with this? I remove everything except the input and output files parameters and I still see the same poor performnace.

+ +

Let’s break this down into 1000 line chunks, and feed each one to say.

+ +
split -d -l 1000 Steve_Jobs_\&_the_NeXT_Big_Thing_1993_djvu.txt Steve1000__
+time for file in Steve1000__*; do time say \
+    -f "$file" \
+    -o "$file.m4b" \
+    --file-format=m4bf \
+    --rate=150 \
+    --progress; done
+
+ +

Well that’s interesting, the process completed in 10 minutes and produced 14 files that comprise the audio book.

+ +

But, I don’t want 14 parts, I’d like, say, three parts of 5000 lines each. I re-run the script … +split -d -l 5000 Steve_Jobs_\&_the_NeXT_Big_Thing_1993_djvu.txt Steve5000__

+ +

And each part takes 30 minutes to generate, a total of 90 minutes of CPU time.

+ +

So, what’s the take away here?

+ +

Intuitively, generating voice from a text file would be a linear operation. Text goes in, Audio goes out, no doubling back through a stream. But, there’s clearly a bug in the implementation of say that makes the run time be something larger than O(n^2). Apparently having say spew out hours of audio for an entire book was never a tested use case. Except, say has been around for as long as MacOSX has been around, one would think all the bugs have been worked out. Apparently not; you have to test and test and test, there will always be surprises.

+:ET \ No newline at end of file diff --git a/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/f2/c91ce0aa21e626a7eaa9ad51b40830e69be74b1d9162085924c4f233e80431 b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/f2/c91ce0aa21e626a7eaa9ad51b40830e69be74b1d9162085924c4f233e80431 new file mode 100644 index 0000000..ddcf48a --- /dev/null +++ b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/f2/c91ce0aa21e626a7eaa9ad51b40830e69be74b1d9162085924c4f233e80431 @@ -0,0 +1,71 @@ +I"Ó

Recently I had to write a file uploader for AWS S3 in node.

+ +

+const AWS = require('aws-sdk');
+const s3 = new AWS.S3({ signatureVersion: 'v4' });
+
+const uploadToS3 = async () => {
+  const parameters = {
+    Bucket: s3Bucket,
+    Body: fileData,
+  };
+
+  try {
+    const { Location } = await s3.upload(parameters).promise();
+    return Location;
+  } catch (e) {
+    process.exit(1);
+  }
+};
+
+ +

It looks simple enough, but you’re probably going to be spending a decent amount of time googling around for examples if the parameters in an s3 call are more than just basic hello world. Add to this javascript is a dynamically typed language; you won’t know if your code will work until you run it, but you’re also working with Amazon’s AWS SDK, it’s derived from Java and expects a few things beyond just numbers and strings. In the end, you’d be beating your head against the stack traces and other HTTP 400 - Bad Request errors coming out of the S3 service.

+ +

Is there anything that can help guarantee your calls to upload are legit with some sort of type checking?

+ +

You’ve probably heard of the type annotated javascript superset language TypeScript and its supplementary type definition repository Definitely Typed, which contains definitions for many popular NPM packages including AWS-SDK. This would be great except switching from Javascript to TypeScript requires adoption from the rest of the team, separate .ts files, and modifications to your build process. Is there any way to get this without futzing with your existing project?

+ +

If you’re using the Visual Studio Code editor it turns out you can enable type checking on a per-file basis by adding the comment to the beginning of the file

+ +
// @ts-check
+
+ +

to the beginning of your file. +typeerror

+ +

The parameters variable is highlighted in red, and when you mouseover it you’ll see:

+ +
Argument of type '{ Bucket: string; Body: string; }' is not assignable to parameter of type 'PutObjectRequest'.
+  Property 'Key' is missing in type '{ Bucket: string; Body: string; }' but required in type 'PutObjectRequest'.ts(2345)
+s3.d.ts(3640, 5): 'Key' is declared here.
+const parameters: {
+    Bucket: string;
+    Body: string;
+}
+
+ +

There are a bunch of things happening here!

+ +

It turns out VS Code has pulled in the AWS S3 type definitions in the background. The type of the parameter parameter that s3.upload takes is called PutObjectRequest. The Type Script compiler is kvetching over a missing required field it needs to say the parameters variable is of that type. There’s nothing stopping you from running the code as it stands here, it’ll just crash at runtime.

+ +

When you add the Key parameter (the unique file key in an S3 bucket), the red squiggly underline disappears and you have a properly formed object.

+ +

The same checking is useful for output types.

+ +
  const { Location } = await s3.upload(parameters).promise();
+
+ +

You can mouseover s3.upload and see it returns a type of AWS.S3.ManagedUpload.SendData, which means the destructuring operation { Location } is guaranteed to work and Location will be populated.

+ +

Links:

+ +

Type Annotation and Checking within javascript + https://github.com/Microsoft/TypeScript/wiki/Type-Checking-JavaScript-Files

+ +

JSDoc - the type annotation here is based after JSDoc, so looking at the docs can’t hurt

+ +

http://usejsdoc.org/tags-type.html

+ +

More to come, as with introducing gradual typing, learning this stuff is also a gradual process that pays you back the more you put into it.

+ +:ET \ No newline at end of file diff --git a/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/f3/66593c605d2558dd7641a3ec129bc92d9fc48b19eea4fe7e0d5f2f5a67b69c b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/f3/66593c605d2558dd7641a3ec129bc92d9fc48b19eea4fe7e0d5f2f5a67b69c new file mode 100644 index 0000000..b368357 --- /dev/null +++ b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/f3/66593c605d2558dd7641a3ec129bc92d9fc48b19eea4fe7e0d5f2f5a67b69c @@ -0,0 +1,4 @@ +I"¦

I like to play around with lots of different programming languages, but install too many and they pollute your working environment, so it’s better to have them installed as a user instead of root. +Here’s a way to get several of them installed into your unix user directory. +If things go wrong, or you get bored you can easily rm -rf the installation.

+:ET \ No newline at end of file diff --git a/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/fa/4279ae7d32fa586eed1fe0a04364cba17a92c68f9530bf0541bc7f96b5197e b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/fa/4279ae7d32fa586eed1fe0a04364cba17a92c68f9530bf0541bc7f96b5197e new file mode 100644 index 0000000..a7e0bec --- /dev/null +++ b/blog/.jekyll-cache/Jekyll/Cache/Jekyll--Converters--Markdown/fa/4279ae7d32fa586eed1fe0a04364cba17a92c68f9530bf0541bc7f96b5197e @@ -0,0 +1,2 @@ +I"I

The Perspicacious Polyglot’s Programming Language Plethora

+:ET \ No newline at end of file diff --git a/blog/.nojekyll b/blog/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/404.html b/blog/404.html similarity index 100% rename from 404.html rename to blog/404.html diff --git a/Gemfile b/blog/Gemfile similarity index 88% rename from Gemfile rename to blog/Gemfile index 2bf1ac7..4f30904 100644 --- a/Gemfile +++ b/blog/Gemfile @@ -8,10 +8,11 @@ source "https://rubygems.org" # # This will help ensure the proper Jekyll version is running. # Happy Jekylling! -gem "jekyll", "~> 3.8.5" +gem "jekyll" # This is the default theme for new Jekyll sites. You may change this to anything you like. -gem "minima", "~> 2.0" +# gem "minima" +gem 'moonwalk' # If you want to use GitHub Pages, remove the "gem "jekyll"" above and # uncomment the line below. To upgrade, run `bundle update github-pages`. @@ -28,3 +29,11 @@ gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby] # Performance-booster for watching directories on Windows gem "wdm", "~> 0.1.0" if Gem.win_platform? +# gem "csv", "~> 3.3.2" + + +gem 'webrick' +gem 'base64' +gem 'csv' +gem 'logger' +gem 'bigdecimal' \ No newline at end of file diff --git a/blog/Gemfile.lock b/blog/Gemfile.lock new file mode 100644 index 0000000..073365a --- /dev/null +++ b/blog/Gemfile.lock @@ -0,0 +1,108 @@ +GEM + remote: https://rubygems.org/ + specs: + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) + base64 (0.2.0) + bigdecimal (3.1.9) + colorator (1.1.0) + concurrent-ruby (1.3.5) + csv (3.3.2) + em-websocket (0.5.3) + eventmachine (>= 0.12.9) + http_parser.rb (~> 0) + eventmachine (1.2.7) + ffi (1.17.1) + ffi (1.17.1-aarch64-linux-gnu) + ffi (1.17.1-aarch64-linux-musl) + ffi (1.17.1-arm-linux-gnu) + ffi (1.17.1-arm-linux-musl) + ffi (1.17.1-arm64-darwin) + ffi (1.17.1-x86-linux-gnu) + ffi (1.17.1-x86-linux-musl) + ffi (1.17.1-x86_64-darwin) + ffi (1.17.1-x86_64-linux-gnu) + ffi (1.17.1-x86_64-linux-musl) + forwardable-extended (2.6.0) + http_parser.rb (0.8.0) + i18n (1.14.7) + concurrent-ruby (~> 1.0) + jekyll (4.1.1) + addressable (~> 2.4) + colorator (~> 1.0) + em-websocket (~> 0.5) + i18n (~> 1.0) + jekyll-sass-converter (~> 2.0) + jekyll-watch (~> 2.0) + kramdown (~> 2.1) + kramdown-parser-gfm (~> 1.0) + liquid (~> 4.0) + mercenary (~> 0.4.0) + pathutil (~> 0.9) + rouge (~> 3.0) + safe_yaml (~> 1.0) + terminal-table (~> 1.8) + jekyll-feed (0.15.1) + jekyll (>= 3.7, < 5.0) + jekyll-sass-converter (2.2.0) + sassc (> 2.0.1, < 3.0) + jekyll-seo-tag (2.7.1) + jekyll (>= 3.8, < 5.0) + jekyll-watch (2.2.1) + listen (~> 3.0) + kramdown (2.4.0) + rexml + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) + liquid (4.0.4) + listen (3.9.0) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + logger (1.6.5) + mercenary (0.4.0) + moonwalk (0.0.2) + jekyll (~> 4.1.1) + jekyll-feed (~> 0.15.0) + jekyll-seo-tag (~> 2.7.1) + pathutil (0.16.2) + forwardable-extended (~> 2.6) + public_suffix (5.1.1) + rb-fsevent (0.11.2) + rb-inotify (0.11.1) + ffi (~> 1.0) + rexml (3.4.0) + rouge (3.30.0) + safe_yaml (1.0.5) + sassc (2.4.0) + ffi (~> 1.9) + terminal-table (1.8.0) + unicode-display_width (~> 1.1, >= 1.1.1) + unicode-display_width (1.8.0) + webrick (1.9.1) + +PLATFORMS + aarch64-linux-gnu + aarch64-linux-musl + arm-linux-gnu + arm-linux-musl + arm64-darwin + ruby + x86-linux-gnu + x86-linux-musl + x86_64-darwin + x86_64-linux-gnu + x86_64-linux-musl + +DEPENDENCIES + base64 + bigdecimal + csv + jekyll + jekyll-feed (~> 0.6) + logger + moonwalk + tzinfo-data + webrick + +BUNDLED WITH + 2.6.3 diff --git a/_config.yml b/blog/_config.yml similarity index 90% rename from _config.yml rename to blog/_config.yml index 86d448b..f61c789 100644 --- a/_config.yml +++ b/blog/_config.yml @@ -23,7 +23,11 @@ github_username: johncsimon # Build settings markdown: kramdown -theme: minima +# remote_theme: pages-themes/hacker@v0.2.0 +theme: moonwalk + +# plugins: +# - jekyll-remote-theme # add this line to the plugins list if you already have one plugins: - jekyll-feed diff --git a/_posts/2018-12-30-javascript-gradual-typing.markdown b/blog/_posts/2018-12-30-javascript-gradual-typing.markdown similarity index 93% rename from _posts/2018-12-30-javascript-gradual-typing.markdown rename to blog/_posts/2018-12-30-javascript-gradual-typing.markdown index 5c94ffe..1f52bc3 100644 --- a/_posts/2018-12-30-javascript-gradual-typing.markdown +++ b/blog/_posts/2018-12-30-javascript-gradual-typing.markdown @@ -2,10 +2,10 @@ layout: post title: "Gradual Typing With Javascript and VS Code" date: 2018-12-29 11:40:43 -0800 -categories: javascript +categories: posts --- -Recently I had to write a file uploader for AWS S3 in node. +Recently I had to write a file uploader for AWS S3 in node. ```javascript @@ -27,18 +27,19 @@ const uploadToS3 = async () => { }; ``` - It looks simple enough, but you're probably going to be spending a decent amount of time googling around for examples if the parameters in an s3 call are more than just basic hello world. Add to this javascript is a dynamically typed language; you won't know if your code will work until you run it, but you're also working with Amazon's AWS SDK, it's derived from Java and expects a few things beyond just numbers and strings. In the end, you'd be beating your head against the stack traces and other `HTTP 400 - Bad Request` errors coming out of the S3 service. -**Is there anything that can help guarantee your calls to `upload` are legit with some sort of type checking?** +**Is there anything that can help guarantee your calls to `upload` are legit with some sort of type checking?** You've probably heard of the type annotated javascript superset language [TypeScript][typescript-site] and its supplementary type definition repository [Definitely Typed][dt-site], which contains definitions for many popular NPM packages including AWS-SDK. This would be great except switching from Javascript to TypeScript requires adoption from the rest of the team, separate `.ts` files, and modifications to your build process. Is there any way to get this without futzing with your existing project? If you're using the Visual Studio Code editor it turns out you can enable [type checking on a per-file basis][type-annotation] by adding the comment to the beginning of the file + ```javascript // @ts-check ``` -to the beginning of your file. + +to the beginning of your file. ![typeerror](typeError.png) The parameters variable is highlighted in red, and when you mouseover it you'll see: @@ -52,19 +53,20 @@ const parameters: { Body: string; } ``` -There are a bunch of things happening here! -It turns out VS Code has pulled in the AWS S3 type definitions in the background. The type of the parameter parameter that `s3.upload` takes is called `PutObjectRequest`. The Type Script compiler is kvetching over a missing required field it needs to say the `parameters` variable is of that type. There's nothing stopping you from running the code as it stands here, it'll just crash at runtime. +There are a bunch of things happening here! -When you add the `Key` parameter (the unique file key in an S3 bucket), the red squiggly underline disappears and you have a properly formed object. +It turns out VS Code has pulled in the AWS S3 type definitions in the background. The type of the parameter parameter that `s3.upload` takes is called `PutObjectRequest`. The Type Script compiler is kvetching over a missing required field it needs to say the `parameters` variable is of that type. There's nothing stopping you from running the code as it stands here, it'll just crash at runtime. +When you add the `Key` parameter (the unique file key in an S3 bucket), the red squiggly underline disappears and you have a properly formed object. The same checking is useful for output types. + ```javascript const { Location } = await s3.upload(parameters).promise(); ``` -You can mouseover s3.upload and see it returns a type of `AWS.S3.ManagedUpload.SendData`, which means the destructuring operation `{ Location }` is guaranteed to work and Location will be populated. +You can mouseover s3.upload and see it returns a type of `AWS.S3.ManagedUpload.SendData`, which means the destructuring operation `{ Location }` is guaranteed to work and Location will be populated. Links: @@ -75,9 +77,8 @@ JSDoc - the type annotation here is based after JSDoc, so looking at the docs ca `http://usejsdoc.org/tags-type.html` - More to come, as with introducing gradual typing, learning this stuff is also a gradual process that pays you back the more you put into it. [typescript-site]: https://www.typescriptlang.org/ [dt-site]: http://definitelytyped.org/ -[type-annotation]: https://github.com/Microsoft/TypeScript/wiki/Type-Checking-JavaScript-Files \ No newline at end of file +[type-annotation]: https://github.com/Microsoft/TypeScript/wiki/Type-Checking-JavaScript-Files diff --git a/_posts/2019-1-16-polyglot-setup.markdown b/blog/_posts/2019-1-16-polyglot-setup.markdown similarity index 100% rename from _posts/2019-1-16-polyglot-setup.markdown rename to blog/_posts/2019-1-16-polyglot-setup.markdown diff --git a/blog/_posts/2025-2-9-poor-mans-audiobook-reader.markdown b/blog/_posts/2025-2-9-poor-mans-audiobook-reader.markdown new file mode 100644 index 0000000..623e2ca --- /dev/null +++ b/blog/_posts/2025-2-9-poor-mans-audiobook-reader.markdown @@ -0,0 +1,72 @@ +--- +layout: post +title: "Poor Man's Audiobook Reader" +date: 2025-02-09T18:04:18.692Z +categories: posts +--- + +I'm currently reading a contemporary history of Steve Jobs's time with the creation and unraveling of NeXT Computer - [Steve Jobs and the NeXT Big Thing](). +![Steve Jobs and the NeXT Big Thing](jobscover.png){: width="250" } + +Today, popular culture paints him as an iconic figure, but when the book was written in 1993 NeXT was a money pit, only kept alive with cash infusions from outside investors as money was burnt. It's a wild ride, I highly recommend it, especially with hindsight. + +Unfortunately, reading books cover to cover is hard for me. I rely on audiobooks so I can ride the bus or do dishes while I absorb a book. Unfortunately, there is no audiobook release of this book. + +I found the book in PDF form on [archive.org](https://archive.org/details/steve_jobs_the_next_big_thing_1993_pdf__mlib). Unfortunately PDFs are more of a page layout language like HTML instead of a store of text. + +If you were to use Text to Speech functionality say - [speak visible content](https://support.apple.com/guide/mac-help/have-your-mac-speak-text-thats-on-the-screen-mh27448/mac) on your PC or phone on a typical website or PDF you have to 'baby sit' what is being read so that the reader doesn't get 'lost' or get caught up on footnotes or stop abruptly or be unable to handle a change in fonts. It's not obvious how broken this functionality is. + +![Speak Visible Content](iostextreader.png){: width="250" } + +**Plain text** is the best for a text to speech program. Luckily, archive.org provides a plain text version of the book which was created via optical character recognition (see the archive.org site). Short of a few footnotes, it's 95% of what we need. + +Except... text to speech generation is a high CPU task, Apple iOS doesn't like long running tasks. You can't scrub back and forth within a document like you can with an audio book or video. Also, it seems that this functionality within iOS doesn't see as much development as other parts of the OS, it's generally a janky experience more optimized for the vision impaired than my use case. + +So, **we need an offline bulk text to speech generator**. Luckily, macOS provides just the very thing hidden as one of the command line utilities - this is the **say** utility `say -v Bad\ News "Captain, you are needed on the bridge" -w 200` but it can take additional parameters (see the man pages "man say" ) + +example call: + +```sh +say --voice=Ava \ # use '?' to get a list of all the available voices + --input-file Steve_Jobs_\&_the_NeXT_Big_Thing_1993_djvu.txt \ # path to plain text file + --data-format=m4b \ # File for the output format, m4b is the apple's audiobook equavalent of m4a see 'say --file-format='?' ' for the list of these + --output-file=MyOutputFile.m4b \ # output file + --rate=150 # speaking rate in words per minute, to your taste. + --progress # print the progress +``` + +This is awesome! But after letting it run for one later the CPU is still at 100% and the process is consuming 2.3 GB of RAM and the output file MyOutoutFile.m4b is about 50 MB on disk. + +Something is up ... let's see the word count of this file. + +``` +wc -lw Steve_Jobs_\&_the_NeXT_Big_Thing_1993_djvu.txt +14908 122808 Steve_Jobs_&_the_NeXT_Big_Thing_1993_djvu.txt +``` + +so 15000 lines, 122000 words - at 150 words / minute this is about 13 hours to read through all of it, and an audiobook of that length is roughly 1 GB. + +Maybe the compression or some other non-default setting is mucking with this? I remove everything except the input and output files parameters and I still see the same poor performnace. + +Let's break this down into 1000 line chunks, and feed each one to **say**. + +``` +split -d -l 1000 Steve_Jobs_\&_the_NeXT_Big_Thing_1993_djvu.txt Steve1000__ +time for file in Steve1000__*; do time say \ + -f "$file" \ + -o "$file.m4b" \ + --file-format=m4bf \ + --rate=150 \ + --progress; done +``` + +Well that's interesting, the process completed in 10 minutes and produced 14 files that comprise the audio book. + +But, I don't want 14 parts, I'd like, say, three parts of 5000 lines each. I re-run the script ... +`split -d -l 5000 Steve_Jobs_\&_the_NeXT_Big_Thing_1993_djvu.txt Steve5000__` + +And each part takes 30 minutes to generate, a total of 90 minutes of CPU time. + +## So, what's the take away here? + +Intuitively, generating voice from a text file would be a linear operation. Text goes in, Audio goes out, no doubling back through a stream. But, there's clearly a bug in the implementation of **say** that makes the run time be something larger than O(n^2). Apparently having **say** spew out hours of audio for an entire book was never a tested use case. Except, **say** has been around for as long as MacOSX has been around, one would think all the bugs have been worked out. Apparently not; you have to test and test and test, there will always be surprises. diff --git a/about.md b/blog/about.md similarity index 100% rename from about.md rename to blog/about.md diff --git a/index.md b/blog/index.md similarity index 100% rename from index.md rename to blog/index.md diff --git a/blog/posts/.DS_Store b/blog/posts/.DS_Store new file mode 100644 index 0000000..12c9459 Binary files /dev/null and b/blog/posts/.DS_Store differ diff --git a/javascript/2018/12/29/typeError.png b/blog/posts/2018/12/29/typeError.png similarity index 100% rename from javascript/2018/12/29/typeError.png rename to blog/posts/2018/12/29/typeError.png diff --git a/blog/posts/2025/02/09/iostextreader.png b/blog/posts/2025/02/09/iostextreader.png new file mode 100644 index 0000000..f2602c9 Binary files /dev/null and b/blog/posts/2025/02/09/iostextreader.png differ diff --git a/blog/posts/2025/02/09/jobscover.png b/blog/posts/2025/02/09/jobscover.png new file mode 100644 index 0000000..3ec7698 Binary files /dev/null and b/blog/posts/2025/02/09/jobscover.png differ diff --git a/buildlocal.sh b/buildlocal.sh new file mode 100755 index 0000000..74d4407 --- /dev/null +++ b/buildlocal.sh @@ -0,0 +1,3 @@ +docker build -t github-pages-local . +docker create --name temp-container github-pages-local +docker run --rm -p 4000:4000 -v $(pwd)/blog:/site github-pages-local diff --git a/buildrelease.sh b/buildrelease.sh new file mode 100755 index 0000000..7984e8b --- /dev/null +++ b/buildrelease.sh @@ -0,0 +1,5 @@ +rm -rf ./docs +docker build -t github-pages-local . +docker create --name temp-container github-pages-local +docker cp temp-container:/output ./docs +docker rm temp-container diff --git a/docs/404.html b/docs/404.html new file mode 100644 index 0000000..1ee03bc --- /dev/null +++ b/docs/404.html @@ -0,0 +1,103 @@ + + + + + + + + + 🌲 johncsimon.github.io 🐦 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+

404

+ +

Page not found :(

+

The requested page could not be found.

+
+ + + +
+
+ + + + + diff --git a/docs/about/index.html b/docs/about/index.html new file mode 100644 index 0000000..b9f0283 --- /dev/null +++ b/docs/about/index.html @@ -0,0 +1 @@ +

I’m a software dev with Go, Javascript and C#. I’m writing this blog to better at writing and to document my explorations.

diff --git a/docs/assets/css/main.css b/docs/assets/css/main.css new file mode 100644 index 0000000..d55c7ed --- /dev/null +++ b/docs/assets/css/main.css @@ -0,0 +1,3 @@ +html{height:100%}body{font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:1.0rem;line-height:2;margin:0;min-height:100%}h2,h3,h4,h5{margin-top:1.5em}hr{margin:1em 0}hr.page-break{text-align:center;border:0}hr.page-break:before{content:'-----'}hr.page-break:after{content:attr(data-content) "-----"}p{margin:1em 0}li{margin:0.4em 0}.w{max-width:720px;margin:0 auto;padding:4em 2em}table,th,td{width:100%;border:thin solid black;border-collapse:collapse;padding:0.4em}div.highlighter-rouge code,code.highlighter-rouge{display:block;overflow-x:auto;padding:1em}blockquote{font-style:italic;border:thin solid black;padding:1em}blockquote p{margin:0}img{max-width:100%;display:block;margin:0 auto}html{--bg: #FFF;--bg-secondary: #F8F9FA;--headings: #000;--text: #333;--links: blue;--highlight: #FFECB2}html[data-theme="dark"] html,html[data-theme="dark"] body{--headings: #74c0fc;--links: #91A7FF;--highlight: #41C7C7;--bg: #1f242A;--bg-secondary: #323945;--text: #adb5bd}@media (prefers-color-scheme: dark){body[data-theme="auto"] html,body[data-theme="auto"] body{--headings: #74c0fc;--links: #91A7FF;--highlight: #41C7C7;--bg: #1f242A;--bg-secondary: #323945;--text: #adb5bd}}html,body{background-color:var(--bg);color:var(--text)}h1,h2,h3,h4,h5,h6{color:var(--headings)}p,strong,b,em,small,li,hr,table,code,figcaption{color:var(--text)}code,blockquote{background-color:var(--bg-secondary);border:1px var(--text) solid}a{color:var(--links)}*:target{background-color:var(--bg-secondary)}html.transition,html.transition *,html.transition *:before,html.transition *:after{transition:all 250ms !important;transition-delay:0 !important}.theme-toggle{color:var(--text);background-color:transparent;padding:4px;cursor:pointer;margin:1em;position:fixed;right:0;top:0;border:2px transparent solid;outline:none}.theme-toggle:hover{color:var(--links);outline:none}.theme-toggle:focus{outline:none}.dashed{border-top:1px var(--text) dashed;margin:0.5em 0}mark{padding:0.4em;background-color:var(--highlight);font-size:0.7em}.post-date{color:var(--headings);margin-right:2em}.share{color:var(--text)}.home-date{font-family:monospace}.post-list-item a{text-decoration:none}.text-bold{font-weight:bold}.text-upcase{text-transform:uppercase}ul.horizontal-list{display:flex;margin-top:0em;margin-left:-40px;flex-wrap:wrap}ul.horizontal-list li{display:inline;margin-right:1em}ul.horizontal-list li a{text-decoration:none;font-weight:normal}.card{padding:1em;border:1px var(--text) solid;width:11em;height:11em;text-align:center;font-size:1em;align-items:center;background-color:var(--bg-secondary);margin-bottom:0.8em}.card .header{color:var(--links)}.card .body{font-size:0.8em}.card hr{margin:0.5em 0}@media screen and (max-width: 600px){ul.horizontal-list li.card{width:100%;display:block;margin-bottom:1em;margin-left:1em}ul.horizontal-list li.card a,ul.horizontal-list li.card .header{font-size:1em}} + +/*# sourceMappingURL=main.css.map */ \ No newline at end of file diff --git a/docs/assets/css/main.css.map b/docs/assets/css/main.css.map new file mode 100644 index 0000000..3633e19 --- /dev/null +++ b/docs/assets/css/main.css.map @@ -0,0 +1,16 @@ +{ + "version": 3, + "file": "main.css", + "sources": [ + "main.scss", + "../usr/local/bundle/gems/moonwalk-0.0.2/_sass/moonwalk.scss", + "../usr/local/bundle/gems/moonwalk-0.0.2/_sass/list.scss" + ], + "sourcesContent": [ + "@import \"moonwalk\";\n@import \"list\";\n", + "html { height: 100%; }\n\nbody {\n font-family: -apple-system,system-ui,BlinkMacSystemFont,\"Segoe UI\",Roboto,\"Helvetica Neue\",Arial,sans-serif;\n font-size: 1.0rem;\n line-height: 2;\n margin: 0;\n min-height: 100%;\n}\n\nh2, h3, h4, h5 { margin-top: 1.5em; }\n\nhr { margin: 1em 0; }\n\nhr.page-break {\n text-align: center;\n border: 0;\n\n &:before { content: '-----' }\n &:after { content: attr(data-content) '-----' }\n}\n\np { margin: 1em 0; }\n\nli { margin: 0.4em 0; }\n\n.w {\n max-width: 720px;\n margin: 0 auto;\n padding: 4em 2em;\n}\n\ntable, th, td {\n width: 100%;\n border: thin solid black;\n border-collapse: collapse;\n padding: 0.4em;\n}\n\ndiv.highlighter-rouge code, code.highlighter-rouge {\n display: block;\n overflow-x: auto;\n padding: 1em;\n}\n\nblockquote {\n font-style: italic;\n border: thin solid black;\n padding: 1em;\n\n p { margin: 0; }\n}\n\nimg {\n max-width: 100%;\n display: block;\n margin: 0 auto;\n}\nhtml {\n --bg: #FFF;\n --bg-secondary: #F8F9FA;\n --headings: #000;\n --text: #333;\n --links: blue;\n //--highlight: #FFD19B;\n --highlight: #FFECB2; // light yellow\n}\n// -------------- THEME SWITCHER -------------- //\n@mixin dark-appearance {\n html, body {\n --headings: #74c0fc;\n --links: #91A7FF;\n --highlight: #41C7C7;\n --bg: #1f242A;\n --bg-secondary: #323945;\n --text: #adb5bd;\n };\n}\nhtml[data-theme=\"dark\"] { @include dark-appearance; }\n\n@media (prefers-color-scheme: dark) {\n body[data-theme=\"auto\"] { @include dark-appearance; }\n}\n// -------------------------------------------- //\n\nhtml, body {\n background-color: var(--bg);\n color: var(--text);\n}\nh1, h2, h3, h4, h5, h6 {\n color: var(--headings);\n}\np, strong, b, em, small, li, hr, table, code, figcaption {\n color: var(--text);\n}\ncode, blockquote {\n background-color: var(--bg-secondary);\n border: 1px var(--text) solid;\n}\na {\n color: var(--links);\n}\n*:target { background-color: var(--bg-secondary); }\n\nhtml.transition,\nhtml.transition *,\nhtml.transition *:before,\nhtml.transition *:after {\n transition: all 250ms !important;\n transition-delay: 0 !important;\n}\n\n.theme-toggle {\n color: var(--text);\n background-color: transparent;\n padding: 4px;\n cursor: pointer;\n margin: 1em;\n position: fixed;\n right: 0;\n top: 0;\n border: 2px transparent solid;\n outline: none;\n}\n\n.theme-toggle:hover {\n color: var(--links);\n outline: none;\n}\n.theme-toggle:focus {\n outline: none;\n}\n.dashed {\n border-top: 1px var(--text) dashed;\n margin: 0.5em 0;\n}\nmark {\n padding: 0.4em;\n background-color: var(--highlight);\n font-size: 0.7em;\n}\n\n.post-date {\n color: var(--headings);\n margin-right: 2em;\n}\n.share {\n color: var(--text);\n}\n.home-date {\n font-family: monospace;\n}\n.post-list-item a {\n text-decoration: none;\n}\n.text-bold {\n font-weight: bold;\n}\n.text-upcase {\n text-transform: uppercase;\n}\n", + "ul.horizontal-list {\n display: flex;\n //justify-content: space-between;\n margin-top: 0em;\n margin-left: -40px;\n flex-wrap: wrap;\n\n li {\n display:inline;\n margin-right: 1em;\n }\n\n li a {\n text-decoration: none;\n font-weight: normal\n }\n\n}\n\n.card {\n padding: 1em;\n border: 1px var(--text) solid;\n width: 11em;\n height: 11em;\n text-align: center;\n font-size: 1em;\n align-items: center;\n background-color: var(--bg-secondary);\n margin-bottom: 0.8em;\n\n .header {\n color: var(--links);\n }\n\n .body {\n font-size: 0.8em;\n }\n\n hr {\n margin: 0.5em 0;\n }\n\n}\n\n/* Responsive cards - one column layout on small screens */\n@media screen and (max-width: 600px) {\n ul.horizontal-list li.card {\n width: 100%;\n display: block;\n margin-bottom: 1em;\n margin-left: 1em;\n a, .header {\n font-size: 1em;\n }\n }\n}\n" + ], + "names": [], + "mappings": "ACAA,AAAA,IAAI,AAAC,CAAE,MAAM,CAAE,IAAI,CAAI,AAEvB,AAAA,IAAI,AAAC,CACH,WAAW,CAAE,8FAA8F,CAC3G,SAAS,CAAE,MAAM,CACjB,WAAW,CAAE,CAAC,CACd,MAAM,CAAE,CAAC,CACT,UAAU,CAAE,IAAI,CACjB,AAED,AAAA,EAAE,CAAE,EAAE,CAAE,EAAE,CAAE,EAAE,AAAC,CAAE,UAAU,CAAE,KAAK,CAAI,AAEtC,AAAA,EAAE,AAAC,CAAE,MAAM,CAAE,KAAK,CAAI,AAEtB,AAAA,EAAE,AAAA,WAAW,AAAC,CACZ,UAAU,CAAE,MAAM,CAClB,MAAM,CAAE,CAAC,CAIV,AAND,AAIE,EAJA,AAAA,WAAW,CAIT,MAAM,AAAC,CAAE,OAAO,CAAE,OAAQ,CAAE,AAJhC,AAKE,EALA,AAAA,WAAW,CAKT,KAAK,AAAC,CAAE,OAAO,CAAE,kBAAkB,CAAC,OAAO,CAAG,AAGlD,AAAA,CAAC,AAAC,CAAE,MAAM,CAAE,KAAK,CAAI,AAErB,AAAA,EAAE,AAAC,CAAE,MAAM,CAAE,OAAO,CAAI,AAExB,AAAA,EAAE,AAAC,CACD,SAAS,CAAE,KAAK,CAChB,MAAM,CAAE,MAAM,CACd,OAAO,CAAE,OAAO,CACjB,AAED,AAAA,KAAK,CAAE,EAAE,CAAE,EAAE,AAAC,CACZ,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,gBAAgB,CACxB,eAAe,CAAE,QAAQ,CACzB,OAAO,CAAE,KAAK,CACf,AAED,AAAA,GAAG,AAAA,kBAAkB,CAAC,IAAI,CAAE,IAAI,AAAA,kBAAkB,AAAC,CACjD,OAAO,CAAE,KAAK,CACd,UAAU,CAAE,IAAI,CAChB,OAAO,CAAE,GAAG,CACb,AAED,AAAA,UAAU,AAAC,CACT,UAAU,CAAE,MAAM,CAClB,MAAM,CAAE,gBAAgB,CACxB,OAAO,CAAE,GAAG,CAGb,AAND,AAKE,UALQ,CAKR,CAAC,AAAC,CAAE,MAAM,CAAE,CAAC,CAAI,AAGnB,AAAA,GAAG,AAAC,CACF,SAAS,CAAE,IAAI,CACf,OAAO,CAAE,KAAK,CACd,MAAM,CAAE,MAAM,CACf,AACD,AAAA,IAAI,AAAC,CACD,IAAI,CAAA,KAAC,CACL,cAAc,CAAA,QAAC,CACf,UAAU,CAAA,KAAC,CACX,MAAM,CAAA,KAAC,CACP,OAAO,CAAA,KAAC,CAER,WAAW,CAAA,QAAC,CACf,AAYD,AATE,IASE,CAAA,AAAA,UAAC,CAAW,MAAM,AAAjB,EATH,IAAI,CASN,IAAI,CAAA,AAAA,UAAC,CAAW,MAAM,AAAjB,EATG,IAAI,AAAE,CACR,UAAU,CAAA,QAAC,CACX,OAAO,CAAA,QAAC,CACR,WAAW,CAAA,QAAC,CACZ,IAAI,CAAA,QAAC,CACL,cAAc,CAAA,QAAC,CACf,MAAM,CAAA,QAAC,CACV,AAIH,MAAM,6BAXJ,CAYA,AAZA,IAYI,CAAA,AAAA,UAAC,CAAW,MAAM,AAAjB,EAZL,IAAI,CAYJ,IAAI,CAAA,AAAA,UAAC,CAAW,MAAM,AAAjB,EAZC,IAAI,AAAE,CACR,UAAU,CAAA,QAAC,CACX,OAAO,CAAA,QAAC,CACR,WAAW,CAAA,QAAC,CACZ,IAAI,CAAA,QAAC,CACL,cAAc,CAAA,QAAC,CACf,MAAM,CAAA,QAAC,CACV,CAAA,AASH,AAAA,IAAI,CAAE,IAAI,AAAC,CACP,gBAAgB,CAAE,SAAS,CAC3B,KAAK,CAAE,WAAW,CACrB,AACD,AAAA,EAAE,CAAE,EAAE,CAAE,EAAE,CAAE,EAAE,CAAE,EAAE,CAAE,EAAE,AAAC,CACnB,KAAK,CAAE,eAAe,CACzB,AACD,AAAA,CAAC,CAAE,MAAM,CAAE,CAAC,CAAE,EAAE,CAAE,KAAK,CAAE,EAAE,CAAE,EAAE,CAAE,KAAK,CAAE,IAAI,CAAE,UAAU,AAAC,CACrD,KAAK,CAAE,WAAW,CACrB,AACD,AAAA,IAAI,CAAE,UAAU,AAAC,CACf,gBAAgB,CAAE,mBAAmB,CACrC,MAAM,CAAE,GAAG,CAAC,WAAW,CAAC,KAAK,CAC9B,AACD,AAAA,CAAC,AAAC,CACA,KAAK,CAAE,YAAY,CACpB,AACD,AAAA,CAAC,CAAC,MAAM,AAAC,CAAE,gBAAgB,CAAE,mBAAmB,CAAI,AAEpD,AAAA,IAAI,AAAA,WAAW,CACf,IAAI,AAAA,WAAW,CAAC,CAAC,CACjB,IAAI,AAAA,WAAW,CAAC,CAAC,CAAC,MAAM,CACxB,IAAI,AAAA,WAAW,CAAC,CAAC,CAAC,KAAK,AAAC,CACpB,UAAU,CAAE,oBAAoB,CAChC,gBAAgB,CAAE,YAAY,CACjC,AAED,AAAA,aAAa,AAAC,CACZ,KAAK,CAAE,WAAW,CAClB,gBAAgB,CAAE,WAAW,CAC7B,OAAO,CAAE,GAAG,CACZ,MAAM,CAAE,OAAO,CACf,MAAM,CAAE,GAAG,CACX,QAAQ,CAAE,KAAK,CACf,KAAK,CAAE,CAAC,CACR,GAAG,CAAE,CAAC,CACN,MAAM,CAAE,qBAAqB,CAC7B,OAAO,CAAE,IAAI,CACd,AAED,AAAA,aAAa,CAAC,KAAK,AAAC,CAClB,KAAK,CAAE,YAAY,CACnB,OAAO,CAAE,IAAI,CACd,AACD,AAAA,aAAa,CAAC,KAAK,AAAC,CAClB,OAAO,CAAE,IAAI,CACd,AACD,AAAA,OAAO,AAAC,CACN,UAAU,CAAE,GAAG,CAAC,WAAW,CAAC,MAAM,CAClC,MAAM,CAAE,OAAO,CAChB,AACD,AAAA,IAAI,AAAC,CACH,OAAO,CAAE,KAAK,CACd,gBAAgB,CAAE,gBAAgB,CAClC,SAAS,CAAE,KAAK,CACjB,AAED,AAAA,UAAU,AAAC,CACT,KAAK,CAAE,eAAe,CACtB,YAAY,CAAE,GAAG,CAClB,AACD,AAAA,MAAM,AAAC,CACL,KAAK,CAAE,WAAW,CACnB,AACD,AAAA,UAAU,AAAC,CACT,WAAW,CAAE,SAAS,CACvB,AACD,AAAA,eAAe,CAAC,CAAC,AAAC,CAChB,eAAe,CAAE,IAAI,CACtB,AACD,AAAA,UAAU,AAAC,CACT,WAAW,CAAE,IAAI,CAClB,AACD,AAAA,YAAY,AAAC,CACX,cAAc,CAAE,SAAS,CAC1B,AChKD,AAAA,EAAE,AAAA,gBAAgB,AAAC,CACjB,OAAO,CAAE,IAAI,CAEb,UAAU,CAAE,GAAG,CACf,WAAW,CAAE,KAAK,CAClB,SAAS,CAAE,IAAI,CAYhB,AAjBD,AAOE,EAPA,AAAA,gBAAgB,CAOhB,EAAE,AAAC,CACD,OAAO,CAAC,MAAM,CACd,YAAY,CAAE,GAAG,CAClB,AAVH,AAYE,EAZA,AAAA,gBAAgB,CAYhB,EAAE,CAAC,CAAC,AAAC,CACH,eAAe,CAAE,IAAI,CACrB,WAAW,CAAE,MACf,CAAC,AAIH,AAAA,KAAK,AAAC,CACJ,OAAO,CAAE,GAAG,CACZ,MAAM,CAAE,GAAG,CAAC,WAAW,CAAC,KAAK,CAC7B,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,MAAM,CAClB,SAAS,CAAE,GAAG,CACd,WAAW,CAAE,MAAM,CACnB,gBAAgB,CAAE,mBAAmB,CACrC,aAAa,CAAE,KAAK,CAcrB,AAvBD,AAWE,KAXG,CAWH,OAAO,AAAC,CACN,KAAK,CAAE,YAAY,CACpB,AAbH,AAeE,KAfG,CAeH,KAAK,AAAC,CACJ,SAAS,CAAE,KAAK,CACjB,AAjBH,AAmBE,KAnBG,CAmBH,EAAE,AAAC,CACD,MAAM,CAAE,OAAO,CAChB,AAKH,MAAM,8BACJ,CAAA,AAAA,EAAE,AAAA,gBAAgB,CAAC,EAAE,AAAA,KAAK,AAAC,CACzB,KAAK,CAAE,IAAI,CACX,OAAO,CAAE,KAAK,CACd,aAAa,CAAE,GAAG,CAClB,WAAW,CAAE,GAAG,CAIjB,AARD,AAKE,EALA,AAAA,gBAAgB,CAAC,EAAE,AAAA,KAAK,CAKxB,CAAC,CALH,EAAE,AAAA,gBAAgB,CAAC,EAAE,AAAA,KAAK,CAKrB,OAAO,AAAC,CACT,SAAS,CAAE,GAAG,CACf,CACF" +} \ No newline at end of file diff --git a/docs/feed.xml b/docs/feed.xml new file mode 100644 index 0000000..89e23fe --- /dev/null +++ b/docs/feed.xml @@ -0,0 +1,349 @@ +Jekyll2025-02-10T08:37:23+00:00https://www.abhinavsaxena.com/moonwalk/feed.xml🌲 johncsimon.github.io 🐦got some downtime so how's about we starts ourselves a blog ...Abhinav SaxenaPoor Man’s Audiobook Reader2025-02-09T18:04:18+00:002025-02-09T18:04:18+00:00https://www.abhinavsaxena.com/moonwalk/posts/2025/02/09/poor-mans-audiobook-reader<p>I’m currently reading a contemporary history of Steve Jobs’s time with the creation and unraveling of NeXT Computer - <a href="https://www.goodreads.com/book/show/226316.Steve_Jobs_the_NeXT_Big_Thing">Steve Jobs and the NeXT Big Thing</a>. +<img src="jobscover.png" alt="Steve Jobs and the NeXT Big Thing" width="250" /></p> + +<p>Today, popular culture paints him as an iconic figure, but when the book was written in 1993 NeXT was a money pit, only kept alive with cash infusions from outside investors as money was burnt. It’s a wild ride, I highly recommend it, especially with hindsight.</p> + +<p>Unfortunately, reading books cover to cover is hard for me. I rely on audiobooks so I can ride the bus or do dishes while I absorb a book. Unfortunately, there is no audiobook release of this book.</p> + +<p>I found the book in PDF form on <a href="https://archive.org/details/steve_jobs_the_next_big_thing_1993_pdf__mlib">archive.org</a>. Unfortunately PDFs are more of a page layout language like HTML instead of a store of text.</p> + +<p>If you were to use Text to Speech functionality say - <a href="https://support.apple.com/guide/mac-help/have-your-mac-speak-text-thats-on-the-screen-mh27448/mac">speak visible content</a> on your PC or phone on a typical website or PDF you have to ā€˜baby sit’ what is being read so that the reader doesn’t get ā€˜lost’ or get caught up on footnotes or stop abruptly or be unable to handle a change in fonts. It’s not obvious how broken this functionality is.</p> + +<p><img src="iostextreader.png" alt="Speak Visible Content" width="250" /></p> + +<p><strong>Plain text</strong> is the best for a text to speech program. Luckily, archive.org provides a plain text version of the book which was created via optical character recognition (see the archive.org site). Short of a few footnotes, it’s 95% of what we need.</p> + +<p>Except… text to speech generation is a high CPU task, Apple iOS doesn’t like long running tasks. You can’t scrub back and forth within a document like you can with an audio book or video. Also, it seems that this functionality within iOS doesn’t see as much development as other parts of the OS, it’s generally a janky experience more optimized for the vision impaired than my use case.</p> + +<p>So, <strong>we need an offline bulk text to speech generator</strong>. Luckily, macOS provides just the very thing hidden as one of the command line utilities - this is the <strong>say</strong> utility <code class="language-plaintext highlighter-rouge">say -v Bad\ News "Captain, you are needed on the bridge" -w 200</code> but it can take additional parameters (see the man pages ā€œman sayā€ )</p> + +<p>example call:</p> + +<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>say <span class="nt">--voice</span><span class="o">=</span>Ava <span class="se">\ </span><span class="c"># use '?' to get a list of all the available voices</span> + <span class="nt">--input-file</span> Steve_Jobs_<span class="se">\&amp;</span>_the_NeXT_Big_Thing_1993_djvu.txt <span class="se">\ </span><span class="c"># path to plain text file</span> + <span class="nt">--data-format</span><span class="o">=</span>m4b <span class="se">\ </span><span class="c"># File for the output format, m4b is the apple's audiobook equavalent of m4a see 'say --file-format='?' ' for the list of these</span> + <span class="nt">--output-file</span><span class="o">=</span>MyOutputFile.m4b <span class="se">\ </span><span class="c"># output file</span> + <span class="nt">--rate</span><span class="o">=</span>150 <span class="c"># speaking rate in words per minute, to your taste.</span> + <span class="nt">--progress</span> <span class="c"># print the progress</span> +</code></pre></div></div> + +<p>This is awesome! But after letting it run for one later the CPU is still at 100% and the process is consuming 2.3 GB of RAM and the output file MyOutoutFile.m4b is about 50 MB on disk.</p> + +<p>Something is up … let’s see the word count of this file.</p> + +<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>wc -lw Steve_Jobs_\&amp;_the_NeXT_Big_Thing_1993_djvu.txt +14908 122808 Steve_Jobs_&amp;_the_NeXT_Big_Thing_1993_djvu.txt +</code></pre></div></div> + +<p>so 15000 lines, 122000 words - at 150 words / minute this is about 13 hours to read through all of it, and an audiobook of that length is roughly 1 GB.</p> + +<p>Maybe the compression or some other non-default setting is mucking with this? I remove everything except the input and output files parameters and I still see the same poor performnace.</p> + +<p>Let’s break this down into 1000 line chunks, and feed each one to <strong>say</strong>.</p> + +<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>split -d -l 1000 Steve_Jobs_\&amp;_the_NeXT_Big_Thing_1993_djvu.txt Steve1000__ +time for file in Steve1000__*; do time say \ + -f "$file" \ + -o "$file.m4b" \ + --file-format=m4bf \ + --rate=150 \ + --progress; done +</code></pre></div></div> + +<p>Well that’s interesting, the process completed in 10 minutes and produced 14 files that comprise the audio book.</p> + +<p>But, I don’t want 14 parts, I’d like, say, three parts of 5000 lines each. I re-run the script … +<code class="language-plaintext highlighter-rouge">split -d -l 5000 Steve_Jobs_\&amp;_the_NeXT_Big_Thing_1993_djvu.txt Steve5000__</code></p> + +<p>And each part takes 30 minutes to generate, a total of 90 minutes of CPU time.</p> + +<h2 id="so-whats-the-take-away-here">So, what’s the take away here?</h2> + +<p>Intuitively, generating voice from a text file would be a linear operation. Text goes in, Audio goes out, no doubling back through a stream. But, there’s clearly a bug in the implementation of <strong>say</strong> that makes the run time be something larger than O(n^2). Apparently having <strong>say</strong> spew out hours of audio for an entire book was never a tested use case. Except, <strong>say</strong> has been around for as long as MacOSX has been around, one would think all the bugs have been worked out. Apparently not; you have to test and test and test, there will always be surprises.</p>Abhinav SaxenaI’m currently reading a contemporary history of Steve Jobs’s time with the creation and unraveling of NeXT Computer - Steve Jobs and the NeXT Big Thing.The Perspicacious Polyglot’s Programming Language Plethora2019-01-17T19:40:43+00:002019-01-17T19:40:43+00:00https://www.abhinavsaxena.com/moonwalk/polyglot/2019/01/17/polyglot-setup<p>I like to play around with lots of different programming languages, but install too many and they pollute your working environment, so it’s better to have them installed as a user instead of root. +Here’s a way to get several of them installed into your unix user directory. +If things go wrong, or you get bored you can easily <code class="language-plaintext highlighter-rouge">rm -rf</code> the installation.</p> + +<h1 id="initial-install">Initial Install</h1> +<p>Let’s get ourselves a minimal debian environment. I’m using docker here, but you can use a native install, or a VM, or Windows Services for Linux with the ubuntu install.</p> +<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>john@BigBox:~/git/JohnCSimon.github.io<span class="nv">$ </span> <span class="nb">sudo </span>docker run <span class="nt">-ti</span> debian /bin/bash +Unable to find image <span class="s1">'debian:latest'</span> locally +latest: Pulling from library/debian +cd8eada9c7bb: Pull <span class="nb">complete +</span>Digest: sha256:58a80e0b6aa4d960ee2a5452b0230c406c47ed30a66555ba753c8e1710a434f5 +Status: Downloaded newer image <span class="k">for </span>debian:latest +root@6d933dddbbcd:/# +</code></pre></div></div> +<p>Just to satisfy my OCD let’s get the latest updates.</p> + +<p><code class="language-plaintext highlighter-rouge">apt update &amp;&amp; apt upgrade -y</code></p> + +<p><code class="language-plaintext highlighter-rouge">apt install gnupg2 curl procps -y</code> + Installs gpg2, curl and ps</p> + +<h1 id="ruby">ruby</h1> +<p><code class="language-plaintext highlighter-rouge">gpg2 --keyserver hkp://pool.sks-keyservers.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB</code></p> + +<p><code class="language-plaintext highlighter-rouge">\curl -sSL https://get.rvm.io | bash -s stable</code></p> + +<p>To start using RVM you need to run <code class="language-plaintext highlighter-rouge">source /etc/profile.d/rvm.sh</code> or re-login to re-load <code class="language-plaintext highlighter-rouge">~/.profile</code></p> + +<p>From here you can run - <code class="language-plaintext highlighter-rouge">rvm list known</code> and you’ll see a list of ruby flavors and individual versions.</p> + +<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># MRI Rubies</span> +<span class="o">[</span>ruby-]1.8.6[-p420] +<span class="o">[</span>ruby-]1.8.7[-head] <span class="c"># security released on head</span> +<span class="o">[</span>ruby-]1.9.1[-p431] +<span class="o">[</span>ruby-]1.9.2[-p330] +<span class="o">[</span>ruby-]1.9.3[-p551] +<span class="o">[</span>ruby-]2.0.0[-p648] +<span class="o">[</span>ruby-]2.1[.10] +<span class="o">[</span>ruby-]2.2[.10] +<span class="o">[</span>ruby-]2.3[.8] +<span class="o">[</span>ruby-]2.4[.5] +<span class="o">[</span>ruby-]2.5[.3] +<span class="o">[</span>ruby-]2.6[.0] +</code></pre></div></div> + +<p>MRI Ruby is the reference version of Ruby so let’s install the latest version.</p> + +<p><code class="language-plaintext highlighter-rouge">rvm install ruby-2.6.0</code></p> + +<p>I’m running debian and rvm might ask for your root password to install some prerequsites from apt before compiling a new version.</p> + +<p>Congrats, you now have a ruby install</p> + +<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>ruby <span class="nt">-v</span> +ruby 2.6.0p0 <span class="o">(</span>2018-12-25 revision 66547<span class="o">)</span> <span class="o">[</span>x86_64-linux] +</code></pre></div></div> + +<p>from here you can now do whatever since I’m blogging this using jekyll</p> + +<p><code class="language-plaintext highlighter-rouge">gem install bundler jekyll</code></p> + +<h1 id="go">go</h1> +<p>Go is a language that releases new versions on a regular basis. +There’s a similar tool to rvm called gvm. It’s a ā€œgo version managerā€ available from here <code class="language-plaintext highlighter-rouge">https://github.com/moovweb/gvm</code> that’ll let you install multiple versions and set $GOPATH and $GOROOT.</p> + +<p>as a regular user:</p> +<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>bash &lt; &lt;<span class="o">(</span>curl <span class="nt">-s</span> <span class="nt">-S</span> <span class="nt">-L</span> https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer<span class="o">)</span> +Cloning from https://github.com/moovweb/gvm.git to /root/.gvm +No existing Go versions detected +Installed GVM v1.0.22 + +Please restart your terminal session or to get started right away run + <span class="sb">`</span><span class="nb">source</span> /root/.gvm/scripts/gvm<span class="sb">`</span> +</code></pre></div></div> + +<p>you should be able to run and see</p> +<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>gvm version +Go Version Manager v1.0.22 installed at /home/john/.gvm +</code></pre></div></div> + +<p>Run <code class="language-plaintext highlighter-rouge">gvm listall</code> +which will give you a list of all the available versions of go.</p> + +<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$gvm</span> listall + +gvm gos <span class="o">(</span>available<span class="o">)</span> + + go1 + go1.0.1 + ... + go1.11rc1 + go1.11rc2 + go1.11.1 + go1.11.2 + go1.11.3 + go1.11.4 + go1.12beta1 + go1.12beta2 +</code></pre></div></div> +<p>of which there are entirely too many.</p> + +<p>From here, we can install go as our user via binary here:</p> + +<p><code class="language-plaintext highlighter-rouge">gvm install go1.4 -B</code></p> + +<p>try it out</p> +<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>go version +go version go1.4 linux/amd64 +</code></pre></div></div> +<p>We can see it gets installed here:</p> +<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">echo</span> <span class="nv">$GOROOT</span> +/home/john/.gvm/gos/go1.4 +</code></pre></div></div> + +<p>From the gvm link earlier, in order to compile a go build environment for versions 1.5 on we require another go build environment. +Go compiles itself! Neat huh?</p> + +<p>As of now the latest version is go1.11.4</p> +<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">export </span><span class="nv">GOROOT_BOOTSTRAP</span><span class="o">=</span><span class="nv">$GOROOT</span> +<span class="nv">$ </span>gvm <span class="nb">install </span>go1.11.4 +</code></pre></div></div> + +<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>go version +go version go1.4 linux/amd64 +</code></pre></div></div> +<p>you can run +<code class="language-plaintext highlighter-rouge">gvm use - select a go version to use (--default to set permanently)</code></p> + +<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>gvm use go1.11.4 <span class="nt">--default</span> +Now using version go1.11.4 +<span class="nv">$ </span>go version +go version go1.11.4 linux/amd64 +<span class="nv">$ </span><span class="nb">echo</span> <span class="nv">$GOROOT</span> +/home/john/.gvm/gos/go1.11.4 +<span class="nv">$ </span><span class="nb">echo</span> <span class="nv">$GOPATH</span> +/home/john/.gvm/pkgsets/go1.11.4/global +<span class="nv">$ </span><span class="nb">ls</span> /home/john/.gvm/gos/go1.11.4 +AUTHORS CONTRIBUTING.md CONTRIBUTORS LICENSE PATENTS README.md VERSION api bin doc favicon.ico lib manifest misc pkg robots.txt src <span class="nb">test +ls</span> <span class="nv">$GOPATH</span> +overlay pkg src +</code></pre></div></div> + +<p>Be sure to set –default so you keep the same version when you relaunch the shell, so that whatever you install stays where you expect it.</p> + +<h1 id="node-js">node js</h1> +<p>node.js, the server side javascript framework</p> + +<p>nvm is Node Version Manager. Install it like this: +<code class="language-plaintext highlighter-rouge">curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash</code></p> + +<p>Since there are major revisions to the javascript language between node 4, 6, 8 I’ve found I’ve had to switch more often between these versions according to project than I did with other languages.</p> + +<p>You can run <code class="language-plaintext highlighter-rouge">nvm ls-remote</code> and get a list of all the node versions available</p> + +<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ nvm +Example: + nvm install 8.0.0 Install a specific version number + nvm use 8.0 Use the latest available 8.0.x release + nvm run 6.10.3 app.js Run app.js using node 6.10.3 + nvm exec 4.8.3 node app.js Run `node app.js` with the PATH pointing to node 4.8.3 + nvm alias default 8.1.0 Set default node version on a shell + nvm alias default node Always default to the latest available node version on a shell +</code></pre></div></div> + +<p>so if you run</p> + +<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>nvm <span class="nb">install </span>10 +Downloading and installing node v10.15.0... +Downloading https://nodejs.org/dist/v10.15.0/node-v10.15.0-linux-x64.tar.gz... +<span class="c">######################################################################## 100.0%</span> +Computing checksum with <span class="nb">sha256sum +</span>Checksums matched! +Now using node v10.15.0 <span class="o">(</span>npm v6.4.1<span class="o">)</span> +Creating default <span class="nb">alias</span>: default -&gt; 10 <span class="o">(</span>-&gt; v10.15.0<span class="o">)</span> + +<span class="nv">$ </span>whereis node +node: /home/john/.nvm/versions/node/v10.15.0/bin/node +</code></pre></div></div> + +<p>and you can set it to be the default so the setting persists between sessions</p> +<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nvm alias default 10 +</code></pre></div></div> + +<p>So now you can run:</p> +<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>node <span class="nt">-v</span> +v10.15.0 +<span class="nv">$ </span>npm <span class="nt">-v</span> +6.4.1 +</code></pre></div></div> + +<h1 id="rust">rust</h1> +<p>Rust is another language that sees regular updates. You’ll just have to check which is the version for the 2015 and 2018 edition.</p> + +<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl https://sh.rustup.rs -sSf | sh + + + +Current installation options: + + default host triple: x86_64-unknown-linux-gnu + default toolchain: stable + modify PATH variable: yes + +1) Proceed with installation (default) +2) Customize installation +3) Cancel installation +&gt; + +select 1 + +To configure your current shell run source $HOME/.cargo/env +</code></pre></div></div> + +<p>add <code class="language-plaintext highlighter-rouge">$HOME/.cargo/env</code> to your path in .bashrc</p> + +<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>whereis cargo +cargo: /home/john/.cargo/bin/cargo +<span class="nv">$ </span>whereis rustc +cargo: /home/john/.cargo/bin/rustc +</code></pre></div></div>Abhinav SaxenaI like to play around with lots of different programming languages, but install too many and they pollute your working environment, so it’s better to have them installed as a user instead of root. Here’s a way to get several of them installed into your unix user directory. If things go wrong, or you get bored you can easily rm -rf the installation.Gradual Typing With Javascript and VS Code2018-12-29T19:40:43+00:002018-12-29T19:40:43+00:00https://www.abhinavsaxena.com/moonwalk/posts/2018/12/29/javascript-gradual-typing<p>Recently I had to write a file uploader for AWS S3 in node.</p> + +<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code> +<span class="kd">const</span> <span class="nx">AWS</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">aws-sdk</span><span class="dl">'</span><span class="p">);</span> +<span class="kd">const</span> <span class="nx">s3</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">AWS</span><span class="p">.</span><span class="nx">S3</span><span class="p">({</span> <span class="na">signatureVersion</span><span class="p">:</span> <span class="dl">'</span><span class="s1">v4</span><span class="dl">'</span> <span class="p">});</span> + +<span class="kd">const</span> <span class="nx">uploadToS3</span> <span class="o">=</span> <span class="k">async</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span> + <span class="kd">const</span> <span class="nx">parameters</span> <span class="o">=</span> <span class="p">{</span> + <span class="na">Bucket</span><span class="p">:</span> <span class="nx">s3Bucket</span><span class="p">,</span> + <span class="na">Body</span><span class="p">:</span> <span class="nx">fileData</span><span class="p">,</span> + <span class="p">};</span> + + <span class="k">try</span> <span class="p">{</span> + <span class="kd">const</span> <span class="p">{</span> <span class="nx">Location</span> <span class="p">}</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">s3</span><span class="p">.</span><span class="nx">upload</span><span class="p">(</span><span class="nx">parameters</span><span class="p">).</span><span class="nx">promise</span><span class="p">();</span> + <span class="k">return</span> <span class="nx">Location</span><span class="p">;</span> + <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span> + <span class="nx">process</span><span class="p">.</span><span class="nx">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> + <span class="p">}</span> +<span class="p">};</span> +</code></pre></div></div> + +<p>It looks simple enough, but you’re probably going to be spending a decent amount of time googling around for examples if the parameters in an s3 call are more than just basic hello world. Add to this javascript is a dynamically typed language; you won’t know if your code will work until you run it, but you’re also working with Amazon’s AWS SDK, it’s derived from Java and expects a few things beyond just numbers and strings. In the end, you’d be beating your head against the stack traces and other <code class="language-plaintext highlighter-rouge">HTTP 400 - Bad Request</code> errors coming out of the S3 service.</p> + +<p><strong>Is there anything that can help guarantee your calls to <code class="language-plaintext highlighter-rouge">upload</code> are legit with some sort of type checking?</strong></p> + +<p>You’ve probably heard of the type annotated javascript superset language <a href="https://www.typescriptlang.org/">TypeScript</a> and its supplementary type definition repository <a href="http://definitelytyped.org/">Definitely Typed</a>, which contains definitions for many popular NPM packages including AWS-SDK. This would be great except switching from Javascript to TypeScript requires adoption from the rest of the team, separate <code class="language-plaintext highlighter-rouge">.ts</code> files, and modifications to your build process. Is there any way to get this without futzing with your existing project?</p> + +<p>If you’re using the Visual Studio Code editor it turns out you can enable <a href="https://github.com/Microsoft/TypeScript/wiki/Type-Checking-JavaScript-Files">type checking on a per-file basis</a> by adding the comment to the beginning of the file</p> + +<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// @ts-check</span> +</code></pre></div></div> + +<p>to the beginning of your file. +<img src="typeError.png" alt="typeerror" /></p> + +<p>The parameters variable is highlighted in red, and when you mouseover it you’ll see:</p> + +<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Argument of type '{ Bucket: string; Body: string; }' is not assignable to parameter of type 'PutObjectRequest'. + Property 'Key' is missing in type '{ Bucket: string; Body: string; }' but required in type 'PutObjectRequest'.ts(2345) +s3.d.ts(3640, 5): 'Key' is declared here. +const parameters: { + Bucket: string; + Body: string; +} +</code></pre></div></div> + +<p>There are a bunch of things happening here!</p> + +<p>It turns out VS Code has pulled in the AWS S3 type definitions in the background. The type of the parameter parameter that <code class="language-plaintext highlighter-rouge">s3.upload</code> takes is called <code class="language-plaintext highlighter-rouge">PutObjectRequest</code>. The Type Script compiler is kvetching over a missing required field it needs to say the <code class="language-plaintext highlighter-rouge">parameters</code> variable is of that type. There’s nothing stopping you from running the code as it stands here, it’ll just crash at runtime.</p> + +<p>When you add the <code class="language-plaintext highlighter-rouge">Key</code> parameter (the unique file key in an S3 bucket), the red squiggly underline disappears and you have a properly formed object.</p> + +<p>The same checking is useful for output types.</p> + +<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="kd">const</span> <span class="p">{</span> <span class="nx">Location</span> <span class="p">}</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">s3</span><span class="p">.</span><span class="nx">upload</span><span class="p">(</span><span class="nx">parameters</span><span class="p">).</span><span class="nx">promise</span><span class="p">();</span> +</code></pre></div></div> + +<p>You can mouseover s3.upload and see it returns a type of <code class="language-plaintext highlighter-rouge">AWS.S3.ManagedUpload.SendData</code>, which means the destructuring operation <code class="language-plaintext highlighter-rouge">{ Location }</code> is guaranteed to work and Location will be populated.</p> + +<p>Links:</p> + +<p>Type Annotation and Checking within javascript + <code class="language-plaintext highlighter-rouge">https://github.com/Microsoft/TypeScript/wiki/Type-Checking-JavaScript-Files</code></p> + +<p>JSDoc - the type annotation here is based after JSDoc, so looking at the docs can’t hurt</p> + +<p><code class="language-plaintext highlighter-rouge">http://usejsdoc.org/tags-type.html</code></p> + +<p>More to come, as with introducing gradual typing, learning this stuff is also a gradual process that pays you back the more you put into it.</p>Abhinav SaxenaRecently I had to write a file uploader for AWS S3 in node. \ No newline at end of file diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..6024455 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,147 @@ + + + + + + + + + 🌲 johncsimon.github.io 🐦 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
    + +
+ +
+ + +

🌲 johncsimon.github.io 🐦

+ +

got some downtime so how's about we starts ourselves a blog ...

+ +
+ + +

Portfolio

+
    + +
+ + + + + + +

Blog

+ + + + + + +

Old Projects

+
    + +
+ + + + + +
+
+
    + +
+ +
+ + + + +
+
+ + + + + diff --git a/docs/polyglot/2019/01/17/polyglot-setup.html b/docs/polyglot/2019/01/17/polyglot-setup.html new file mode 100644 index 0000000..a19354a --- /dev/null +++ b/docs/polyglot/2019/01/17/polyglot-setup.html @@ -0,0 +1,309 @@ + + + + + + + + + The Perspicacious Polyglot's Programming Language Plethora + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ home.. +

The Perspicacious Polyglot's Programming Language Plethora

+

I like to play around with lots of different programming languages, but install too many and they pollute your working environment, so it’s better to have them installed as a user instead of root. +Here’s a way to get several of them installed into your unix user directory. +If things go wrong, or you get bored you can easily rm -rf the installation.

+ +

Initial Install

+

Let’s get ourselves a minimal debian environment. I’m using docker here, but you can use a native install, or a VM, or Windows Services for Linux with the ubuntu install.

+
john@BigBox:~/git/JohnCSimon.github.io$  sudo docker run -ti debian /bin/bash
+Unable to find image 'debian:latest' locally
+latest: Pulling from library/debian
+cd8eada9c7bb: Pull complete
+Digest: sha256:58a80e0b6aa4d960ee2a5452b0230c406c47ed30a66555ba753c8e1710a434f5
+Status: Downloaded newer image for debian:latest
+root@6d933dddbbcd:/#
+
+

Just to satisfy my OCD let’s get the latest updates.

+ +

apt update && apt upgrade -y

+ +

apt install gnupg2 curl procps -y + Installs gpg2, curl and ps

+ +

ruby

+

gpg2 --keyserver hkp://pool.sks-keyservers.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB

+ +

\curl -sSL https://get.rvm.io | bash -s stable

+ +

To start using RVM you need to run source /etc/profile.d/rvm.sh or re-login to re-load ~/.profile

+ +

From here you can run - rvm list known and you’ll see a list of ruby flavors and individual versions.

+ +
# MRI Rubies
+[ruby-]1.8.6[-p420]
+[ruby-]1.8.7[-head] # security released on head
+[ruby-]1.9.1[-p431]
+[ruby-]1.9.2[-p330]
+[ruby-]1.9.3[-p551]
+[ruby-]2.0.0[-p648]
+[ruby-]2.1[.10]
+[ruby-]2.2[.10]
+[ruby-]2.3[.8]
+[ruby-]2.4[.5]
+[ruby-]2.5[.3]
+[ruby-]2.6[.0]
+
+ +

MRI Ruby is the reference version of Ruby so let’s install the latest version.

+ +

rvm install ruby-2.6.0

+ +

I’m running debian and rvm might ask for your root password to install some prerequsites from apt before compiling a new version.

+ +

Congrats, you now have a ruby install

+ +
$ ruby -v
+ruby 2.6.0p0 (2018-12-25 revision 66547) [x86_64-linux]
+
+ +

from here you can now do whatever since I’m blogging this using jekyll

+ +

gem install bundler jekyll

+ +

go

+

Go is a language that releases new versions on a regular basis. +There’s a similar tool to rvm called gvm. It’s a ā€œgo version managerā€ available from here https://github.com/moovweb/gvm that’ll let you install multiple versions and set $GOPATH and $GOROOT.

+ +

as a regular user:

+
$ bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
+Cloning from https://github.com/moovweb/gvm.git to /root/.gvm
+No existing Go versions detected
+Installed GVM v1.0.22
+
+Please restart your terminal session or to get started right away run
+ `source /root/.gvm/scripts/gvm`
+
+ +

you should be able to run and see

+
$ gvm version
+Go Version Manager v1.0.22 installed at /home/john/.gvm
+
+ +

Run gvm listall +which will give you a list of all the available versions of go.

+ +
$gvm listall
+
+gvm gos (available)
+
+   go1
+   go1.0.1
+   ...
+   go1.11rc1
+   go1.11rc2
+   go1.11.1
+   go1.11.2
+   go1.11.3
+   go1.11.4
+   go1.12beta1
+   go1.12beta2
+
+

of which there are entirely too many.

+ +

From here, we can install go as our user via binary here:

+ +

gvm install go1.4 -B

+ +

try it out

+
$ go version
+go version go1.4 linux/amd64
+
+

We can see it gets installed here:

+
$ echo $GOROOT
+/home/john/.gvm/gos/go1.4
+
+ +

From the gvm link earlier, in order to compile a go build environment for versions 1.5 on we require another go build environment. +Go compiles itself! Neat huh?

+ +

As of now the latest version is go1.11.4

+
$ export GOROOT_BOOTSTRAP=$GOROOT
+$ gvm install go1.11.4
+
+ +
$ go version
+go version go1.4 linux/amd64
+
+

you can run +gvm use - select a go version to use (--default to set permanently)

+ +
$ gvm use go1.11.4 --default
+Now using version go1.11.4
+$ go version
+go version go1.11.4 linux/amd64
+$ echo $GOROOT
+/home/john/.gvm/gos/go1.11.4
+$ echo $GOPATH
+/home/john/.gvm/pkgsets/go1.11.4/global
+$ ls /home/john/.gvm/gos/go1.11.4
+AUTHORS  CONTRIBUTING.md  CONTRIBUTORS  LICENSE  PATENTS  README.md  VERSION  api  bin  doc  favicon.ico  lib  manifest  misc  pkg  robots.txt  src  test
+ls $GOPATH
+overlay  pkg  src
+
+ +

Be sure to set –default so you keep the same version when you relaunch the shell, so that whatever you install stays where you expect it.

+ +

node js

+

node.js, the server side javascript framework

+ +

nvm is Node Version Manager. Install it like this: +curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash

+ +

Since there are major revisions to the javascript language between node 4, 6, 8 I’ve found I’ve had to switch more often between these versions according to project than I did with other languages.

+ +

You can run nvm ls-remote and get a list of all the node versions available

+ +
$ nvm
+Example:
+  nvm install 8.0.0                     Install a specific version number
+  nvm use 8.0                           Use the latest available 8.0.x release
+  nvm run 6.10.3 app.js                 Run app.js using node 6.10.3
+  nvm exec 4.8.3 node app.js            Run `node app.js` with the PATH pointing to node 4.8.3
+  nvm alias default 8.1.0               Set default node version on a shell
+  nvm alias default node                Always default to the latest available node version on a shell
+
+ +

so if you run

+ +
$ nvm install 10
+Downloading and installing node v10.15.0...
+Downloading https://nodejs.org/dist/v10.15.0/node-v10.15.0-linux-x64.tar.gz...
+######################################################################## 100.0%
+Computing checksum with sha256sum
+Checksums matched!
+Now using node v10.15.0 (npm v6.4.1)
+Creating default alias: default -> 10 (-> v10.15.0)
+
+$ whereis node
+node: /home/john/.nvm/versions/node/v10.15.0/bin/node
+
+ +

and you can set it to be the default so the setting persists between sessions

+
nvm alias default 10
+
+ +

So now you can run:

+
$ node -v
+v10.15.0
+$ npm -v
+6.4.1
+
+ +

rust

+

Rust is another language that sees regular updates. You’ll just have to check which is the version for the 2015 and 2018 edition.

+ +
curl https://sh.rustup.rs -sSf | sh
+
+
+
+Current installation options:
+
+   default host triple: x86_64-unknown-linux-gnu
+     default toolchain: stable
+  modify PATH variable: yes
+
+1) Proceed with installation (default)
+2) Customize installation
+3) Cancel installation
+>
+
+select 1 
+
+To configure your current shell run source $HOME/.cargo/env
+
+ +

add $HOME/.cargo/env to your path in .bashrc

+ +
$ whereis cargo
+cargo: /home/john/.cargo/bin/cargo
+$ whereis rustc
+cargo: /home/john/.cargo/bin/rustc
+
+ + + + + +
+
+ + + + + diff --git a/docs/posts/2018/12/29/javascript-gradual-typing.html b/docs/posts/2018/12/29/javascript-gradual-typing.html new file mode 100644 index 0000000..0cd8b93 --- /dev/null +++ b/docs/posts/2018/12/29/javascript-gradual-typing.html @@ -0,0 +1,158 @@ + + + + + + + + + Gradual Typing With Javascript and VS Code + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ home.. +

Gradual Typing With Javascript and VS Code

+

Recently I had to write a file uploader for AWS S3 in node.

+ +

+const AWS = require('aws-sdk');
+const s3 = new AWS.S3({ signatureVersion: 'v4' });
+
+const uploadToS3 = async () => {
+  const parameters = {
+    Bucket: s3Bucket,
+    Body: fileData,
+  };
+
+  try {
+    const { Location } = await s3.upload(parameters).promise();
+    return Location;
+  } catch (e) {
+    process.exit(1);
+  }
+};
+
+ +

It looks simple enough, but you’re probably going to be spending a decent amount of time googling around for examples if the parameters in an s3 call are more than just basic hello world. Add to this javascript is a dynamically typed language; you won’t know if your code will work until you run it, but you’re also working with Amazon’s AWS SDK, it’s derived from Java and expects a few things beyond just numbers and strings. In the end, you’d be beating your head against the stack traces and other HTTP 400 - Bad Request errors coming out of the S3 service.

+ +

Is there anything that can help guarantee your calls to upload are legit with some sort of type checking?

+ +

You’ve probably heard of the type annotated javascript superset language TypeScript and its supplementary type definition repository Definitely Typed, which contains definitions for many popular NPM packages including AWS-SDK. This would be great except switching from Javascript to TypeScript requires adoption from the rest of the team, separate .ts files, and modifications to your build process. Is there any way to get this without futzing with your existing project?

+ +

If you’re using the Visual Studio Code editor it turns out you can enable type checking on a per-file basis by adding the comment to the beginning of the file

+ +
// @ts-check
+
+ +

to the beginning of your file. +typeerror

+ +

The parameters variable is highlighted in red, and when you mouseover it you’ll see:

+ +
Argument of type '{ Bucket: string; Body: string; }' is not assignable to parameter of type 'PutObjectRequest'.
+  Property 'Key' is missing in type '{ Bucket: string; Body: string; }' but required in type 'PutObjectRequest'.ts(2345)
+s3.d.ts(3640, 5): 'Key' is declared here.
+const parameters: {
+    Bucket: string;
+    Body: string;
+}
+
+ +

There are a bunch of things happening here!

+ +

It turns out VS Code has pulled in the AWS S3 type definitions in the background. The type of the parameter parameter that s3.upload takes is called PutObjectRequest. The Type Script compiler is kvetching over a missing required field it needs to say the parameters variable is of that type. There’s nothing stopping you from running the code as it stands here, it’ll just crash at runtime.

+ +

When you add the Key parameter (the unique file key in an S3 bucket), the red squiggly underline disappears and you have a properly formed object.

+ +

The same checking is useful for output types.

+ +
  const { Location } = await s3.upload(parameters).promise();
+
+ +

You can mouseover s3.upload and see it returns a type of AWS.S3.ManagedUpload.SendData, which means the destructuring operation { Location } is guaranteed to work and Location will be populated.

+ +

Links:

+ +

Type Annotation and Checking within javascript + https://github.com/Microsoft/TypeScript/wiki/Type-Checking-JavaScript-Files

+ +

JSDoc - the type annotation here is based after JSDoc, so looking at the docs can’t hurt

+ +

http://usejsdoc.org/tags-type.html

+ +

More to come, as with introducing gradual typing, learning this stuff is also a gradual process that pays you back the more you put into it.

+ + + + + +
+
+ + + + + diff --git a/docs/posts/2018/12/29/typeError.png b/docs/posts/2018/12/29/typeError.png new file mode 100644 index 0000000..209314a Binary files /dev/null and b/docs/posts/2018/12/29/typeError.png differ diff --git a/docs/posts/2025/02/09/iostextreader.png b/docs/posts/2025/02/09/iostextreader.png new file mode 100644 index 0000000..f2602c9 Binary files /dev/null and b/docs/posts/2025/02/09/iostextreader.png differ diff --git a/docs/posts/2025/02/09/jobscover.png b/docs/posts/2025/02/09/jobscover.png new file mode 100644 index 0000000..3ec7698 Binary files /dev/null and b/docs/posts/2025/02/09/jobscover.png differ diff --git a/docs/posts/2025/02/09/poor-mans-audiobook-reader.html b/docs/posts/2025/02/09/poor-mans-audiobook-reader.html new file mode 100644 index 0000000..a9d4589 --- /dev/null +++ b/docs/posts/2025/02/09/poor-mans-audiobook-reader.html @@ -0,0 +1,150 @@ + + + + + + + + + Poor Man's Audiobook Reader + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ home.. +

Poor Man's Audiobook Reader

+

I’m currently reading a contemporary history of Steve Jobs’s time with the creation and unraveling of NeXT Computer - Steve Jobs and the NeXT Big Thing. +Steve Jobs and the NeXT Big Thing

+ +

Today, popular culture paints him as an iconic figure, but when the book was written in 1993 NeXT was a money pit, only kept alive with cash infusions from outside investors as money was burnt. It’s a wild ride, I highly recommend it, especially with hindsight.

+ +

Unfortunately, reading books cover to cover is hard for me. I rely on audiobooks so I can ride the bus or do dishes while I absorb a book. Unfortunately, there is no audiobook release of this book.

+ +

I found the book in PDF form on archive.org. Unfortunately PDFs are more of a page layout language like HTML instead of a store of text.

+ +

If you were to use Text to Speech functionality say - speak visible content on your PC or phone on a typical website or PDF you have to ā€˜baby sit’ what is being read so that the reader doesn’t get ā€˜lost’ or get caught up on footnotes or stop abruptly or be unable to handle a change in fonts. It’s not obvious how broken this functionality is.

+ +

Speak Visible Content

+ +

Plain text is the best for a text to speech program. Luckily, archive.org provides a plain text version of the book which was created via optical character recognition (see the archive.org site). Short of a few footnotes, it’s 95% of what we need.

+ +

Except… text to speech generation is a high CPU task, Apple iOS doesn’t like long running tasks. You can’t scrub back and forth within a document like you can with an audio book or video. Also, it seems that this functionality within iOS doesn’t see as much development as other parts of the OS, it’s generally a janky experience more optimized for the vision impaired than my use case.

+ +

So, we need an offline bulk text to speech generator. Luckily, macOS provides just the very thing hidden as one of the command line utilities - this is the say utility say -v Bad\ News "Captain, you are needed on the bridge" -w 200 but it can take additional parameters (see the man pages ā€œman sayā€ )

+ +

example call:

+ +
say --voice=Ava \ # use '?' to get a list of all the available voices
+    --input-file Steve_Jobs_\&_the_NeXT_Big_Thing_1993_djvu.txt \ # path to plain text file
+    --data-format=m4b \ # File for the output format, m4b is the apple's audiobook equavalent of m4a see 'say --file-format='?' ' for the list of these
+    --output-file=MyOutputFile.m4b \ # output file
+    --rate=150 # speaking rate in words per minute, to your taste.
+    --progress # print the progress
+
+ +

This is awesome! But after letting it run for one later the CPU is still at 100% and the process is consuming 2.3 GB of RAM and the output file MyOutoutFile.m4b is about 50 MB on disk.

+ +

Something is up … let’s see the word count of this file.

+ +
wc -lw Steve_Jobs_\&_the_NeXT_Big_Thing_1993_djvu.txt
+14908  122808 Steve_Jobs_&_the_NeXT_Big_Thing_1993_djvu.txt
+
+ +

so 15000 lines, 122000 words - at 150 words / minute this is about 13 hours to read through all of it, and an audiobook of that length is roughly 1 GB.

+ +

Maybe the compression or some other non-default setting is mucking with this? I remove everything except the input and output files parameters and I still see the same poor performnace.

+ +

Let’s break this down into 1000 line chunks, and feed each one to say.

+ +
split -d -l 1000 Steve_Jobs_\&_the_NeXT_Big_Thing_1993_djvu.txt Steve1000__
+time for file in Steve1000__*; do time say \
+    -f "$file" \
+    -o "$file.m4b" \
+    --file-format=m4bf \
+    --rate=150 \
+    --progress; done
+
+ +

Well that’s interesting, the process completed in 10 minutes and produced 14 files that comprise the audio book.

+ +

But, I don’t want 14 parts, I’d like, say, three parts of 5000 lines each. I re-run the script … +split -d -l 5000 Steve_Jobs_\&_the_NeXT_Big_Thing_1993_djvu.txt Steve5000__

+ +

And each part takes 30 minutes to generate, a total of 90 minutes of CPU time.

+ +

So, what’s the take away here?

+ +

Intuitively, generating voice from a text file would be a linear operation. Text goes in, Audio goes out, no doubling back through a stream. But, there’s clearly a bug in the implementation of say that makes the run time be something larger than O(n^2). Apparently having say spew out hours of audio for an entire book was never a tested use case. Except, say has been around for as long as MacOSX has been around, one would think all the bugs have been worked out. Apparently not; you have to test and test and test, there will always be surprises.

+ + + + +
+
+ + + + + diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..853f8ba --- /dev/null +++ b/readme.md @@ -0,0 +1,6 @@ +# I got a blog + +``` +buildlocal.sh - builds and runs jekyll in docker +buildrelease.sh - builds and runs jekyll in docker +```