From bda44e93541fa478abf3ce4b3461f026a90fa8cb Mon Sep 17 00:00:00 2001 From: Thomas Voss Date: Mon, 11 Sep 2023 05:15:20 +0200 Subject: Move the site from HTML to GSP --- src/prj/index.gsp | 40 ++ src/prj/index.html | 45 -- src/prj/mkpass/basic-usage.sh.gsp | 6 + src/prj/mkpass/basic-usage.sh.html | 6 - src/prj/mkpass/index.gsp | 106 ++++ src/prj/mkpass/index.html | 102 ---- src/prj/mkpass/length-flag.sh.gsp | 4 + src/prj/mkpass/length-flag.sh.html | 4 - "src/prj/mmv/camel-to-snake-na\303\257ve.sh.gsp" | 2 + "src/prj/mmv/camel-to-snake-na\303\257ve.sh.html" | 2 - src/prj/mmv/camel-to-snake-smart.sh.gsp | 1 + src/prj/mmv/camel-to-snake-smart.sh.html | 1 - src/prj/mmv/examples/camel-to-snake.sh.gsp | 1 + src/prj/mmv/examples/camel-to-snake.sh.html | 1 - src/prj/mmv/examples/hyphens.sh.gsp | 1 + src/prj/mmv/examples/hyphens.sh.html | 1 - src/prj/mmv/examples/i-flag.sh.gsp | 1 + src/prj/mmv/examples/i-flag.sh.html | 1 - src/prj/mmv/examples/lowercase.sh.gsp | 1 + src/prj/mmv/examples/lowercase.sh.html | 1 - src/prj/mmv/examples/number.sh.gsp | 2 + src/prj/mmv/examples/number.sh.html | 2 - src/prj/mmv/examples/swap.sh.gsp | 1 + src/prj/mmv/examples/swap.sh.html | 1 - src/prj/mmv/examples/vipe.sh.gsp | 1 + src/prj/mmv/examples/vipe.sh.html | 1 - src/prj/mmv/index.gsp | 645 +++++++++++++++++++++ src/prj/mmv/index.html | 667 ---------------------- src/prj/mmv/ls-files.sh.gsp | 2 + src/prj/mmv/ls-files.sh.html | 2 - src/prj/mmv/manual-mv.sh.gsp | 5 + src/prj/mmv/manual-mv.sh.html | 5 - src/prj/mmv/mmv-rev-zero.sh.gsp | 2 + src/prj/mmv/mmv-rev-zero.sh.html | 2 - src/prj/mmv/mmv-rev.sh.gsp | 2 + src/prj/mmv/mmv-rev.sh.html | 2 - src/prj/mmv/mmv-tr.sh.gsp | 1 + src/prj/mmv/mmv-tr.sh.html | 1 - src/prj/mmv/mmv-verbose.sh.gsp | 8 + src/prj/mmv/mmv-verbose.sh.html | 8 - src/prj/mmv/reverse-embedded-newline.sh.gsp | 3 + src/prj/mmv/reverse-embedded-newline.sh.html | 3 - src/prj/mmv/sed-debugging-rev.sh.gsp | 3 + src/prj/mmv/sed-debugging-rev.sh.html | 3 - src/prj/mmv/sed-debugging.sh.gsp | 3 + src/prj/mmv/sed-debugging.sh.html | 3 - src/prj/mmv/sha1sum-long-example.sh.gsp | 11 + src/prj/mmv/sha1sum-long-example.sh.html | 11 - src/prj/mmv/sha1sum-short-example.sh.gsp | 6 + src/prj/mmv/sha1sum-short-example.sh.html | 6 - src/prj/mmv/tr.sh.gsp | 3 + src/prj/mmv/tr.sh.html | 3 - src/prj/mmv/vim.gsp | 2 + src/prj/mmv/vim.html | 2 - src/prj/mmv/vipe.sh.gsp | 1 + src/prj/mmv/vipe.sh.html | 1 - src/prj/totp/basic-usage.sh.gsp | 7 + src/prj/totp/basic-usage.sh.html | 7 - src/prj/totp/index.gsp | 134 +++++ src/prj/totp/index.html | 140 ----- src/prj/totp/zbarimg.sh.gsp | 4 + src/prj/totp/zbarimg.sh.html | 4 - 62 files changed, 1009 insertions(+), 1038 deletions(-) create mode 100644 src/prj/index.gsp delete mode 100644 src/prj/index.html create mode 100644 src/prj/mkpass/basic-usage.sh.gsp delete mode 100644 src/prj/mkpass/basic-usage.sh.html create mode 100644 src/prj/mkpass/index.gsp delete mode 100644 src/prj/mkpass/index.html create mode 100644 src/prj/mkpass/length-flag.sh.gsp delete mode 100644 src/prj/mkpass/length-flag.sh.html create mode 100644 "src/prj/mmv/camel-to-snake-na\303\257ve.sh.gsp" delete mode 100644 "src/prj/mmv/camel-to-snake-na\303\257ve.sh.html" create mode 100644 src/prj/mmv/camel-to-snake-smart.sh.gsp delete mode 100644 src/prj/mmv/camel-to-snake-smart.sh.html create mode 100644 src/prj/mmv/examples/camel-to-snake.sh.gsp delete mode 100644 src/prj/mmv/examples/camel-to-snake.sh.html create mode 100644 src/prj/mmv/examples/hyphens.sh.gsp delete mode 100644 src/prj/mmv/examples/hyphens.sh.html create mode 100644 src/prj/mmv/examples/i-flag.sh.gsp delete mode 100644 src/prj/mmv/examples/i-flag.sh.html create mode 100644 src/prj/mmv/examples/lowercase.sh.gsp delete mode 100644 src/prj/mmv/examples/lowercase.sh.html create mode 100644 src/prj/mmv/examples/number.sh.gsp delete mode 100644 src/prj/mmv/examples/number.sh.html create mode 100644 src/prj/mmv/examples/swap.sh.gsp delete mode 100644 src/prj/mmv/examples/swap.sh.html create mode 100644 src/prj/mmv/examples/vipe.sh.gsp delete mode 100644 src/prj/mmv/examples/vipe.sh.html create mode 100644 src/prj/mmv/index.gsp delete mode 100644 src/prj/mmv/index.html create mode 100644 src/prj/mmv/ls-files.sh.gsp delete mode 100644 src/prj/mmv/ls-files.sh.html create mode 100644 src/prj/mmv/manual-mv.sh.gsp delete mode 100644 src/prj/mmv/manual-mv.sh.html create mode 100644 src/prj/mmv/mmv-rev-zero.sh.gsp delete mode 100644 src/prj/mmv/mmv-rev-zero.sh.html create mode 100644 src/prj/mmv/mmv-rev.sh.gsp delete mode 100644 src/prj/mmv/mmv-rev.sh.html create mode 100644 src/prj/mmv/mmv-tr.sh.gsp delete mode 100644 src/prj/mmv/mmv-tr.sh.html create mode 100644 src/prj/mmv/mmv-verbose.sh.gsp delete mode 100644 src/prj/mmv/mmv-verbose.sh.html create mode 100644 src/prj/mmv/reverse-embedded-newline.sh.gsp delete mode 100644 src/prj/mmv/reverse-embedded-newline.sh.html create mode 100644 src/prj/mmv/sed-debugging-rev.sh.gsp delete mode 100644 src/prj/mmv/sed-debugging-rev.sh.html create mode 100644 src/prj/mmv/sed-debugging.sh.gsp delete mode 100644 src/prj/mmv/sed-debugging.sh.html create mode 100644 src/prj/mmv/sha1sum-long-example.sh.gsp delete mode 100644 src/prj/mmv/sha1sum-long-example.sh.html create mode 100644 src/prj/mmv/sha1sum-short-example.sh.gsp delete mode 100644 src/prj/mmv/sha1sum-short-example.sh.html create mode 100644 src/prj/mmv/tr.sh.gsp delete mode 100644 src/prj/mmv/tr.sh.html create mode 100644 src/prj/mmv/vim.gsp delete mode 100644 src/prj/mmv/vim.html create mode 100644 src/prj/mmv/vipe.sh.gsp delete mode 100644 src/prj/mmv/vipe.sh.html create mode 100644 src/prj/totp/basic-usage.sh.gsp delete mode 100644 src/prj/totp/basic-usage.sh.html create mode 100644 src/prj/totp/index.gsp delete mode 100644 src/prj/totp/index.html create mode 100644 src/prj/totp/zbarimg.sh.gsp delete mode 100644 src/prj/totp/zbarimg.sh.html (limited to 'src/prj') diff --git a/src/prj/index.gsp b/src/prj/index.gsp new file mode 100644 index 0000000..a5da5ca --- /dev/null +++ b/src/prj/index.gsp @@ -0,0 +1,40 @@ +html lang="en" { + head { m4_include(head.gsp) } + body { + header { + div { + h1 {-My Projects} + m4_include(nav.gsp) + } + + figure .quote { + blockquote { + p {= + Computers make it easier to do a lot of things, but most of the + things they make it easier to do don’t need to be done. + } + } + figcaption {-Andy Rooney} + } + } + + main { + p {- + In this section of the website I cover some of my projects. Some are + completed, some are ongoing; really I’ll just add a post here if I ever + have something I feel is interesting enough to share. + } + + p {-Posts:} + ul { + li {a href="totp" {-totp — generate TOTP codes}} + li {a href="mkpass" {-mkpass — make a password}} + li {a href="mmv" {-mmv, mpc — mapped file moves and -copies}} + } + } + + hr{} + + footer { m4_footer } + } +} diff --git a/src/prj/index.html b/src/prj/index.html deleted file mode 100644 index b8c8bc9..0000000 --- a/src/prj/index.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - m4_include(head.html) - - -
-
-

My Projects

- m4_include(nav.html) -
- -
-
-

Computers make it easier to do a lot of things, but most of the - things they make it easier to do don’t need to be done.

-
-
- Andy Rooney -
-
-
- -
-

- In this section of the website I cover some of my projects. Some are - completed, some are ongoing; really I’ll just add a post here if I ever - have something I feel is interesting enough to share. -

- -

Posts:

- -
- -
- - - - diff --git a/src/prj/mkpass/basic-usage.sh.gsp b/src/prj/mkpass/basic-usage.sh.gsp new file mode 100644 index 0000000..bd8ddf7 --- /dev/null +++ b/src/prj/mkpass/basic-usage.sh.gsp @@ -0,0 +1,6 @@ +$ @span .sh-fn {-mkpass} +m4_gsp_quote(⁨;%_)1S%wYO-unC6%D2pz9'bx^YFI>"VX;T[jzOUsiUr}r/R#T0Qs*XMT*fUef|2L⁩)m4_dnl +$ @span .sh-fn {-mkpass} a-zA-Z0-9 +qTneHVHfwH3b1nCanKKW24lIcsRO2TUAgp7AGbZInfsV8ZjdsR35ZikHIzyUu06x +$ @span .sh-fn {-mkpass} [:alpha:][:digit:] +JlGe9kLOT1ik3CRvOb8VxHqHzluG6oLJ9VI8BVGFTn2lODu3pvTv5ZqeXy3XfT1R diff --git a/src/prj/mkpass/basic-usage.sh.html b/src/prj/mkpass/basic-usage.sh.html deleted file mode 100644 index ab1aca8..0000000 --- a/src/prj/mkpass/basic-usage.sh.html +++ /dev/null @@ -1,6 +0,0 @@ -$ mkpass -;%_)1S%wYO-unC6%D2pz9'bx^YFI>"VX;T[jzOUsiUr}r/R#T0Qs*XMT*fUef|2L -$ mkpass a-zA-Z0-9 -qTneHVHfwH3b1nCanKKW24lIcsRO2TUAgp7AGbZInfsV8ZjdsR35ZikHIzyUu06x -$ mkpass [:alpha:][:digit:] -JlGe9kLOT1ik3CRvOb8VxHqHzluG6oLJ9VI8BVGFTn2lODu3pvTv5ZqeXy3XfT1R diff --git a/src/prj/mkpass/index.gsp b/src/prj/mkpass/index.gsp new file mode 100644 index 0000000..a7ff910 --- /dev/null +++ b/src/prj/mkpass/index.gsp @@ -0,0 +1,106 @@ +html lang="en" { + head { m4_include(head.gsp) } + body { + header { + div { + h1 {-Easy Password Generation} + m4_include(nav.gsp) + } + + figure .quote { + blockquote { + p {= + Why does JavaScript suck? The answer is simple: history. + JavaScript was created by a really smart guy called Brendan Eich + over a period of a week or so. He did it because Microsoft was + largely perceived as evil, and his aim was to create a programming + platform in the Netscape navigator. That way, the browser would run + everywhere, and the OS wouldn't matter as much. HAHA! Down with + Microsoft. You can see how well that worked out. + } + } + figcaption {-Sahil Malik} + } + } + + main { + p { + em {- + You can find the @code{-mkpass} git repository over at + @a + href="https://git.sr.ht/~mango/mkpass" + target="_blank" + {-sourcehut} + or + @a + href="https://github.com/Mango0x45/mkpass" + target="_blank" + {-GitHub}. + } + } + + h2 {-Table of Contents} + ul { + li {a href="#prologue" {-Prologue}} + li {a href="#usage" {-Basic Usage}} + } + + h2 #prologue {-Prologue} + p {- + Password generators are incredibly useful for those who don’t use the + same password everywhere. The issue is that everyone uses the same + password everywhere. Hopefully when people see how easy password + generation can be, that’ll change; there really is no excuse to not use + different passwords these days. @code{-mkpass} aims to be the absolute + simplest password generator possible while still providing the + functionality you need.ls + } + + p {- + Two factor authentication is also something you should be using — and + something that is very easy to manage — and something that I will be + posting about shortly™. + } + + h2 #usage {-Basic Usage} + p {- + The most basic usage of @code{-mkpass} is to just call @code{-mkpass}. + By default this will generate a 64-character password made up of random + printable characters. If you need to use specific characters (for + example, maybe you can only use alphanumeric characters) then you can + simply specify a + @code { + a + href="https://www.man7.org/linux/man-pages/man1/tr.1.html" + target="_blank" + {-tr(1)} + } + style range: + } + + figure { + pre { m4_fmt_code(basic-usage.sh.gsp) } + } + + p {- + You can also specify the length of the password using + the @code{--l} flag: + } + + figure { + pre { m4_fmt_code(length-flag.sh.gsp) } + } + + p {- + And that ladies and gentlemen, is the entire program. A nice minimal + tool that does one thing and one thing only, while integrating nicely + with the UNIX environment. This is (in my opinion), an example of + well-designed software. + } + } + + hr{} + + footer { m4_footer } + } +} diff --git a/src/prj/mkpass/index.html b/src/prj/mkpass/index.html deleted file mode 100644 index 8180358..0000000 --- a/src/prj/mkpass/index.html +++ /dev/null @@ -1,102 +0,0 @@ - - - - m4_include(head.html) - - -
-
-

Easy Password Generation

- m4_include(nav.html) -
- -
-
-

Why does JavaScript suck? The answer is simple: history. JavaScript - was created by a really smart guy called Brendan Eich over a period of - a week or so. He did it because Microsoft was largely perceived as - evil, and his aim was to create a programming platform in the Netscape - navigator. That way, the browser would run everywhere, and the OS - wouldn't matter as much. HAHA! Down with Microsoft. You can see how - well that worked out.

-
-
- Sahil Malik -
-
-
- -
-

- - You can find the mkpass git repository over at - sourcehut - or GitHub. - -

- -

Table of Contents

- - - -

Prologue

-

- Password generators are incredibly useful for those who don’t use the - same password everywhere. The issue is that everyone uses the same - password everywhere. Hopefully when people see how easy password - generation can be, that’ll change; there really is no excuse to not use - different passwords these days. mkpass aims to be the - absolute simplest password generator possible while still providing the - functionality you need.ls -

- -

- Two factor authentication is also something you should be using — and - something that is very easy to manage — and something that I will be - posting about shortly™. -

- -

Basic Usage

-

- The most basic usage of mkpass is to just - call mkpass. By default this will generate a 64-character - password made up of random printable characters. If you need to use - specific characters (for example, maybe you can only use alphanumeric - characters) then you can simply specify a - tr(1) style range: -

- -
-
m4_fmt_code(basic-usage.sh.html)
-
- -

- You can also specify the length of the password using - the -l flag: -

- -
-
m4_fmt_code(length-flag.sh.html)
-
- -

- And that ladies and gentlemen, is the entire program. A nice minimal - tool that does one thing and one thing only, while integrating nicely - with the UNIX environment. This is (in my opinion), an example of - well-designed software. -

-
- -
- - - - diff --git a/src/prj/mkpass/length-flag.sh.gsp b/src/prj/mkpass/length-flag.sh.gsp new file mode 100644 index 0000000..24ed26e --- /dev/null +++ b/src/prj/mkpass/length-flag.sh.gsp @@ -0,0 +1,4 @@ +$ @span .sh-fn {-mkpass} a-z +hxjgusvfxzfasluhlkxvsdszxbzoffkyruauiggigjmhptivctnudnkiararlwcn +$ @span .sh-fn {-mkpass} -l 12 a-z +wymyggnmwkwz diff --git a/src/prj/mkpass/length-flag.sh.html b/src/prj/mkpass/length-flag.sh.html deleted file mode 100644 index f9405a1..0000000 --- a/src/prj/mkpass/length-flag.sh.html +++ /dev/null @@ -1,4 +0,0 @@ -$ mkpass a-z -hxjgusvfxzfasluhlkxvsdszxbzoffkyruauiggigjmhptivctnudnkiararlwcn -$ mkpass -l 12 a-z -wymyggnmwkwz diff --git "a/src/prj/mmv/camel-to-snake-na\303\257ve.sh.gsp" "b/src/prj/mmv/camel-to-snake-na\303\257ve.sh.gsp" new file mode 100644 index 0000000..cd0d156 --- /dev/null +++ "b/src/prj/mmv/camel-to-snake-na\303\257ve.sh.gsp" @@ -0,0 +1,2 @@ +@span .sh-cmt {-# If you aren’t a shell-guru, take a moment to figure out how this works!} +$ @span .sh-fn {-ls} *.[ch] | @span .sh-fn {-sed} @span .sh-str {-'p; s/[A-Z]/\\L_&/g'} | @span .sh-fn {-xargs} -L2 mv diff --git "a/src/prj/mmv/camel-to-snake-na\303\257ve.sh.html" "b/src/prj/mmv/camel-to-snake-na\303\257ve.sh.html" deleted file mode 100644 index 573da41..0000000 --- "a/src/prj/mmv/camel-to-snake-na\303\257ve.sh.html" +++ /dev/null @@ -1,2 +0,0 @@ -# If you aren’t a shell-guru, take a moment to figure out how this works! -$ ls *.[ch] | sed 'p; s/[A-Z]/\L_&/g' | xargs -L2 mv diff --git a/src/prj/mmv/camel-to-snake-smart.sh.gsp b/src/prj/mmv/camel-to-snake-smart.sh.gsp new file mode 100644 index 0000000..9ce6123 --- /dev/null +++ b/src/prj/mmv/camel-to-snake-smart.sh.gsp @@ -0,0 +1 @@ +$ @span .sh-fn {-ls} *.[ch] | @span .sh-fn {-mmv} sed @span .sh-str {-'s/[A-Z]/\\L_&/g'} diff --git a/src/prj/mmv/camel-to-snake-smart.sh.html b/src/prj/mmv/camel-to-snake-smart.sh.html deleted file mode 100644 index 191e87f..0000000 --- a/src/prj/mmv/camel-to-snake-smart.sh.html +++ /dev/null @@ -1 +0,0 @@ -$ ls *.[ch] | mmv sed 's/[A-Z]/\L_&/g' diff --git a/src/prj/mmv/examples/camel-to-snake.sh.gsp b/src/prj/mmv/examples/camel-to-snake.sh.gsp new file mode 100644 index 0000000..7948861 --- /dev/null +++ b/src/prj/mmv/examples/camel-to-snake.sh.gsp @@ -0,0 +1 @@ +$ @span .sh-fn {-git} ls-files @span .sh-str {-'*.[ch]'} | @span .sh-fn {-mmv} sed @span .sh-str {-'s/[A-Z]/\\L_&/g'} diff --git a/src/prj/mmv/examples/camel-to-snake.sh.html b/src/prj/mmv/examples/camel-to-snake.sh.html deleted file mode 100644 index bd67492..0000000 --- a/src/prj/mmv/examples/camel-to-snake.sh.html +++ /dev/null @@ -1 +0,0 @@ -$ git ls-files '*.[ch]' | mmv sed 's/[A-Z]/\L_&/g' diff --git a/src/prj/mmv/examples/hyphens.sh.gsp b/src/prj/mmv/examples/hyphens.sh.gsp new file mode 100644 index 0000000..8f9cc76 --- /dev/null +++ b/src/prj/mmv/examples/hyphens.sh.gsp @@ -0,0 +1 @@ +$ @span .sh-fn {-ls} | @span .sh-fn {-mmv} tr ' ' '-' diff --git a/src/prj/mmv/examples/hyphens.sh.html b/src/prj/mmv/examples/hyphens.sh.html deleted file mode 100644 index ca49946..0000000 --- a/src/prj/mmv/examples/hyphens.sh.html +++ /dev/null @@ -1 +0,0 @@ -$ ls | mmv tr ' ' '-' diff --git a/src/prj/mmv/examples/i-flag.sh.gsp b/src/prj/mmv/examples/i-flag.sh.gsp new file mode 100644 index 0000000..6977635 --- /dev/null +++ b/src/prj/mmv/examples/i-flag.sh.gsp @@ -0,0 +1 @@ +$ @span .sh-fn {-ls} --zero | @span .sh-fn {-mmv} -0i cmd diff --git a/src/prj/mmv/examples/i-flag.sh.html b/src/prj/mmv/examples/i-flag.sh.html deleted file mode 100644 index c22c7c9..0000000 --- a/src/prj/mmv/examples/i-flag.sh.html +++ /dev/null @@ -1 +0,0 @@ -$ ls --zero | mmv -0i cmd diff --git a/src/prj/mmv/examples/lowercase.sh.gsp b/src/prj/mmv/examples/lowercase.sh.gsp new file mode 100644 index 0000000..72a8e4c --- /dev/null +++ b/src/prj/mmv/examples/lowercase.sh.gsp @@ -0,0 +1 @@ +$ @span .sh-fn {-find} . -print0 | @span .sh-fn {-mmv} -0 tr A-Z a-z diff --git a/src/prj/mmv/examples/lowercase.sh.html b/src/prj/mmv/examples/lowercase.sh.html deleted file mode 100644 index 84abb92..0000000 --- a/src/prj/mmv/examples/lowercase.sh.html +++ /dev/null @@ -1 +0,0 @@ -$ find . -print0 | mmv -0 tr A-Z a-z diff --git a/src/prj/mmv/examples/number.sh.gsp b/src/prj/mmv/examples/number.sh.gsp new file mode 100644 index 0000000..ce82f24 --- /dev/null +++ b/src/prj/mmv/examples/number.sh.gsp @@ -0,0 +1,2 @@ +$ @span .sh-fn {-ls} @span .sh-str {-'The Fellowship of the Ring.mp4'} … @span .sh-str {-'The Two Towers.mp4'} | \\ + @span .sh-fn {-mmv} awk @span .sh-str {-'{ gsub(" ", "-"); printf "%02d-%s", NR, tolower($0) \}'} diff --git a/src/prj/mmv/examples/number.sh.html b/src/prj/mmv/examples/number.sh.html deleted file mode 100644 index 5e8e74a..0000000 --- a/src/prj/mmv/examples/number.sh.html +++ /dev/null @@ -1,2 +0,0 @@ -$ ls 'The Fellowship of the Ring.mp4''The Two Towers.mp4' | \ - mmv awk '{ gsub(" ", "-"); printf "%02d-%s", NR, tolower($0) }' diff --git a/src/prj/mmv/examples/swap.sh.gsp b/src/prj/mmv/examples/swap.sh.gsp new file mode 100644 index 0000000..0249751 --- /dev/null +++ b/src/prj/mmv/examples/swap.sh.gsp @@ -0,0 +1 @@ +$ @span .sh-fn {-ls} foo bar | @span .sh-fn {-mmv} tac diff --git a/src/prj/mmv/examples/swap.sh.html b/src/prj/mmv/examples/swap.sh.html deleted file mode 100644 index 02c9c28..0000000 --- a/src/prj/mmv/examples/swap.sh.html +++ /dev/null @@ -1 +0,0 @@ -$ ls foo bar | mmv tac diff --git a/src/prj/mmv/examples/vipe.sh.gsp b/src/prj/mmv/examples/vipe.sh.gsp new file mode 100644 index 0000000..b738ae1 --- /dev/null +++ b/src/prj/mmv/examples/vipe.sh.gsp @@ -0,0 +1 @@ +$ @span .sh-fn {-ls} | @span .sh-fn {-mmv} -0e vipe diff --git a/src/prj/mmv/examples/vipe.sh.html b/src/prj/mmv/examples/vipe.sh.html deleted file mode 100644 index 933039a..0000000 --- a/src/prj/mmv/examples/vipe.sh.html +++ /dev/null @@ -1 +0,0 @@ -$ ls | mmv -0e vipe diff --git a/src/prj/mmv/index.gsp b/src/prj/mmv/index.gsp new file mode 100644 index 0000000..3c2fd97 --- /dev/null +++ b/src/prj/mmv/index.gsp @@ -0,0 +1,645 @@ +html lang="en" { + head { m4_include(head.gsp) } + body { + header { + div { + h1 {-Moving Files the Right Way} + m4_include(nav.gsp) + } + + figure .quote { + blockquote { + p {= + I think the OpenBSD crowd is a bunch of masturbating monkeys, in + that they make such a big deal about concentrating on security to + the point where they pretty much admit that nothing else matters to + them. + } + } + figcaption {-Linus Torvalds} + } + } + + main { + p { + em {- + You can find the @code{-mmv} git repository over at + @a + href="https://git.sr.ht/~mango/mmv" + target="_blank" + {-sourcehut} + or + @a + href="https://github.com/Mango0x45/mmv" + target="_blank" + {-GitHub}. + } + } + + p {- + NOTE: As of the + @a href="https://git.sr.ht/~mango/mmv/refs/v1.2.0" {-v1.2.0} + release there is now also the @code{-mcp} utility. It behaves the same + as the @code{-mmv} utility but it copies files instead of moving them. + It also doesn’t support the ‘@code{--n}’ flag as it doesn’t need to deal + with backups. + } + + h2 {-Table of Contents} + + ul { + li {a href="#prologue" {-Prologue}} + li {a href="#moving" {-Advanced Moving and Pitfalls}} + li {a href="#mapping" {-Name Mapping with @code{-mmv}}} + li {a href="#newlines" {-Filenames with Embedded Newlines}} + ul { + li {a href="0-flag" {-The Simple Case}} + li {a href="#e-flag" {-Encoding Newlines}} + } + li {a href="#i-flag" {-Individual Execution}} + li {a href="#safety" {-Safety}} + li {a href="#examples" {-Examples}} + } + + h2 #prologue {-Prologue} + p {- + File moving and renaming is one of the most common tasks we undertake on + the command-line. We basically always do this with the @code{-mv} + utility, and it gets the job done most of the time. Want to rename one + file? Use @code{-mv}! Want to move a bunch of files into a directory? + Use @code{-mv}! How could mv ever go wrong? Well I’m glad you asked! + } + + h2 #moving {-Advanced Moving and Pitfalls} + p {- + Let’s start off nice and simple. You just inherited a C project that + uses the sacrilegious + @a + href="https://en.wikipedia.org/wiki/Camel_case" + target="_blank" + {-camelCase} + naming convention for its files: + } + + figure { + pre { m4_fmt_code(ls-files.sh.gsp) } + } + + p {- + This deeply upsets you, as it upsets me. So you decide you want to + switch all these files to use + @a + href="https://en.wikipedia.org/wiki/Snake_case" + target="_blank" + {-snake_case}, + like a normal person. Well how would you do this? You use @code{-mv}! + This is what you might end up doing: + } + + figure { + pre { m4_fmt_code(manual-mv.sh.gsp) } + } + + p {- + Well… it works I guess, but it’s a pretty shitty way of renaming these + files. Luckily we only had 5, but what if this was a much larger + project with many more files to rename? Things would get tedious. So + instead we can use a pipeline for this: + } + + figure { + pre { m4_fmt_code(camel-to-snake-naïve.sh.gsp) } + } + + aside { + p {- + The given example assumes your @code{-sed} implementation supports + ‘@code{-\\L}’ which is a non-standard m4_abbr(GNU) extension. + } + } + + p {- + That works and it gets the job done, but it’s not really ideal is + it? There are a couple of issues with this. + } + + ol { + li { + p {- + You’re writing more complicated code. This has the obvious drawback + of potentially being more error-prone, but also risks taking more + time to write than you’d like as you might have forgotten if + @code{-xargs} actually has an ‘@code{--L}’ option or not (which + would require reading the + @a + href="https://www.man7.org/linux/man-pages/man1/xargs.1.html" + target="_blank" + { + code {-xargs(1)} + } + manual). + } + } + li { + p {- + If you try to rename the file @em{-foo} to @em{-bar} but @em{-bar} + already exists, you end up deleting a file you may not have wanted + to. + } + } + li { + p {- + In a similar vein to the previous point, you need to be very careful + about schemes like renaming the file @em{-a} to @em{-b} and @em{-b} + to @em{-c}. You run the risk of turning @em{-a} into @em{-c} and + losing the file @em{-b} entirely. + } + } + li { + p {- + Moving symbolic links is its own whole can of worms. If a symlink + points to a relative location then you need to make sure you keep + pointing to the right place. If the symlink is absolute however + then you can leave it untouched. But what if the symlink points to + a file that you’re moving as part of your batch move operation? Now + you need to handle that too. + } + } + } + + h2 #mapping {-Name Mapping with @code{-mmv}} + + p {- + What is @code{-mmv}? It’s the solution to all your problems, that’s + what it is! @code{-mmv} takes as its argument(s) a utility and that + utilities arguments and uses that to create a mapping between old and + new filenames — similar to the @code{-map()} function found in many + programming languages. I think to best convey how the tool functions, I + should provide an example. Let’s try to do the same thing we did + previously where we tried to turn camelCase files to snake_case, but + using @code{-mmv}: + } + + figure { + pre { m4_fmt_code(camel-to-snake-smart.sh.gsp) } + } + + p {-Let me break down how this works.} + + p {- + @code{-mmv} starts by reading a series of filenames separated by + newlines from the standard input. Yes, sometimes filenames have + newlines in them and yes there is a way to handle them but I shall get + to that later. The filenames that @code{-mmv} reads from the standard + input will be referred to as the @em{-input files}. Once all the input + files have been read, the utility specified by the arguments is spawned; + in this case that would be @code{-sed} with the argument + @code{-'s/[A-Z]/\\L_&/g'}. The input files are then piped into + @code{-sed} the exact same way that they would have been if we ran the + above commands without @code{-mmv}, and the output of @code{-sed} then + forms what will be referred to as the @em{-output files}. Once a + complete list of output files is accumulated, each input file gets + renamed to its corresponding output file. + } + + p {- + Let’s look at a simpler example. Say we want to rename 2 files in the + current directory to use lowercase letters, we could use the following + command: + } + + figure { + pre { m4_fmt_code(mmv-tr.sh.gsp) } + } + + p {- + In the above example @code{-mmv} reads 2 lines from standard input, + those being @em{-LICENSE} and @em{-README}. Those are our 2 input files + now. The @code{-tr} utility is then spawned and the input files are + piped into it. We can simulate this in the shell: + } + + figure { + pre { m4_fmt_code(tr.sh.gsp) } + } + + p {- + As you can see above, @code{-tr} has produced 2 lines of output; these + are our 2 output files. Since we now have our 2 input files and 2 + output files, @code{-mmv} can go ahead and rename the files. In this + case it will rename @em{-LICENSE} to @em{-license} and @em{-README} to + @em{-readme}. For some examples, check the @a href="#examples" + {-examples} section of this page down below. + } + + h2 #newlines {-Filenames with Embedded Newlines} + + p {- + People are retarded, and as a result we have filenames with newlines in + them. All it would have taken to solve this issue for everyone was for + literally @strong{-anybody} during the early UNIX days to go “@em{-hey, + this is a bad idea!}”, but alas, we must deal with this. Newlines are + of course not the only special characters filenames can contain, but + they are the single most infuriating to deal with; the UNIX utilities + all being line-oriented really doesn’t work well with these files. + } + + p {- + So how does @code{-mmv} deal with special characters, and newlines in + particular? Well it does so by providing the user with the @code{--0} + and @code{--e} flags: + } + + dl { + dt { code{--0} } + dd { + p {- + Tell @code{-mmv} to expect its input to not be separated by newlines + (‘@code{-\\n}’), but by NUL bytes (‘@code{-\\0}’). NUL bytes are + the only characters not allowed in filenames besides forward + slashes, so they are an obvious choice for an alternative separator. + } + } + dt { code{--e} } + dd { + p {- + Encode newlines in filenames before passing them to the provided + utility. Newline characters are replaced by the literal string + ‘@code{-\\n}’ and backslashes by the literal string ‘@code{-\\\\}’. + After processing, the resulting output is decoded again. + } + p {- + If combined with the @code{--0} flag, then while input will be read + assuming a NUL-byte input-seperator, the encoded input files will be + written to the spawned process newline-seperated. + } + } + } + + h3 id="0-flag" {-The Simple Case} + + p {- + In order to better understand these flags and how they work let’s go + though another example. We have 2 files — one with and one without an + embedded newline — and our goal is to simply reverse these filenames. + In this example I am going to be displaying newlines in filenames with + the “@code{-$'\\n'}” syntax as this is how my shell displays embedded + newlines. + } + + p {- + We can start by just trying to naïvely pass these 2 files to @code{-mmv} + and use @code{-rev} to reverse the names, but this doesn’t work: + } + + figure { + pre { m4_fmt_code(mmv-rev.sh.gsp) } + } + + p {- + The reason this doesn’t work is because due to the line-oriented nature + of @code{-ls} and @code{-rev}, we are actually trying to rename the + files @em{-foo}, @em{-bar}, and @em{-baz} to the new filenames + @em{-zab}, @em{-rab}, and @em{-oof}. As can be seen in the following + diagram, the embedded newline is causing our input to be ambiguous and + @code{-mmv} can’t reliably proceed anymore @x-ref{-1}: + } + + figure { + object data="conflict.svg" type="image/svg+xml" {-} + } + + aside { + p data-ref="1" {- + The reason you get a cryptic “file not found” error message is because + @code{-mmv} tries to assert that all the input files actually exist + before doing anything. Since “foo” isn’t a real file, we error out. + } + } + + p {- + The first thing we need to do in order to proceed is to pass the + @code{--0} flag to @code{-mmv}. This will tell @code{-mmv} that we want + to use the NUL-byte as our input separator and not the newline. We also + need @code{-ls} to actually provide us with the filenames delimited by + NUL-bytes. Luckily m4_abbr(GNU) @code{-ls} gives us the @code{---zero} + flag to do just that: + } + + figure { + pre { m4_fmt_code(mmv-rev-zero.sh.gsp) } + } + + p {- + So we’re getting places, but we aren’t quite there yet. The issue we’re + getting now is that @code{-mmv} recieved 2 input files from the standard + input, but @code{-rev} produced 3 output files. Why is that? Well + let’s try our hand at a little bit of command-line debugging with + @code{-sed}: + } + + figure { + pre { m4_fmt_code(sed-debugging.sh.gsp) } + } + + p {- + If you aren’t quite sure what the above is doing, here’s a quick + summary: + } + + ul { + li {- + The @code{--U} flag given to @code{-ls} tells it not to sort our + output. This is purely just to keep this example clear to the reader. + } + li {- + The @code{--n} flag given to @code{-sed} tells it not to print the + input line automatically at the end of the provided script. + } + li {- + The @code{-l} command in @code{-sed} prints the current input in a + “visually unambiguous form”. + } + } + + p {- + In the @code{-sed} output, we can see that @samp{-$} represents the end + of a line, and @samp{-\\000} represents the NUL-byte. All looks good + here, we have two inputs seperated by NUL-bytes. Now let’s try to throw + in @code{-rev}: + } + + figure { + pre { m4_fmt_code(sed-debugging-rev.sh.gsp) } + } + + p {- + Well wouldn’t you know it? Since @code{-rev} @em{-also} works with + newline-seperated input, it reversed out NUL-byte seperators and now + gives us 3 outputs. Luckily the folks over at @em{-util-linux} provided + us with the @code{--0} flag here too, so that we can properly handle + NUL-delimited input. Combining all of this together we get a final + working product: + } + + figure { + pre { m4_fmt_code(reverse-embedded-newline.sh.gsp) } + } + + h3 #e-flag {-Encoding Newlines} + + p {- + Sometimes we want to rename a bunch of files, but the command we want to + use doesn’t support NUL-bytes as nicely as we would like. In these + cases, you may want to consider encoding your newline characters into + the literal string ‘@code{-\\n}’ and then passing your input + newline-seperated to your given command with the @code{--e} flag. + } + + p {- + For a real-world example, perhaps you want to edit some filenames in + vim, or whatever other editor you use. Well we can do this incredibly + easily with the @code{-vipe} utility from the + @a href="https://joeyh.name/code/moreutils/" {-moreutils} + collection. The @code{-vipe} command simply reads input from the + standard input, opens it up in your editor, and then prints the + resulting output to the standard output; perfect for @code{-mmv}! We do + not really want to deal with NUL-bytes in our text-editor though, so + let’s just encode our newlines: + } + + figure { + pre { m4_fmt_code(vipe.sh.gsp) } + } + + aside { + p {- + Notice how you still need to pass the @code{--0} flag to @code{-mmv} + know that our inputfiles may have embedded newlines. + } + } + + p {- + When running the above code example, you will see the following in your + editor: + } + + figure { + pre { m4_fmt_code(vim.gsp) } + } + + p {- + After you exit your editor, @code{-mmv} will decode all occurances of + ‘@code{-\\n}’ back into a newline, and all occurances of ‘@code{-\\\\}’ + back into a backslash: + } + + figure { + object data="e-flag.svg" type="image/svg+xml" {-} + } + + h2 #i-flag {-Individual Execution} + p {- + The previous examples are great and all, but what do you do if your + mapping command doesn’t have the concept of an input seperator at all? + This is where the @code{--i} flag comes into play. With the @code{--i} + flag we can get @code{-mmv} to execute our mapping command for every + input filename. This means that as long as we can work with a complete + buffer, we don’t need to worry about seperators. + } + + p {- + To be honest, I cannot really think of any situation where you might + actually need to do this. If you can think of one, please @a + href="mailto:mail@thomasvoss.com" {-email me} and I’ll update the + example on this page. Regardless, let’s imagine that we wanted to + rename some files so that their filenames are replaced with their + filename + @a + href="https://en.wikipedia.org/wiki/SHA-1" + target="_blank" + {-m4_abbr(SHA)-1 hash}. + On Linux we have the @code{-sha1sum} program which reads input from the + standard input and outputs the m4_abbr(SHA)-1 hash. This is how we + would use it with @code{-mmv}: + } + + figure { + pre { m4_fmt_code(sha1sum-long-example.sh.gsp) } + } + + p {- + Another approach is to invoke @code{-mmv} twice: + } + + figure { + pre { m4_fmt_code(sha1sum-short-example.sh.gsp) } + } + + p {- + If you are confused about why we need to make a call to @code{-awk}, + it’s because the @code{-sha1sum} program outputs 2 columns of data. The + first column is our hash and the second column is the filename where the + to-be-hashed data was read from. We don’t want the second column. + } + + p {- + Unlike in previous examples where one process was spawned to map all our + filenames, with the @code{--i} flag we are spawning a new instance for + each filename. If you struggle to visualize this, perhaps the following + diagrams help: + } + + figure { + figcaption {-Invoking @code{-mmv} without @code{--i}} + object data="without-i-flag.svg" type="image/svg+xml" {-} + } + + figure { + figcaption {-Invoking @code{-mmv} with @code{--i}} + object data="with-i-flag.svg" type="image/svg+xml" {-} + } + + h2 #safety {-Safety} + p {- + When compared to the standard @code{-for f in *; do mv $f …; done} or + @code{-ls | … | xargs -L2 mv} constructs, @code{-mmv} is significantly + more safe to use. These are some of the safety features that are built + into the tool: + } + + ol { + li {- + If the number of input- and output files differs, execution is aborted + before making any changes. + } + li {- + If an input file is renamed to the name of another input file, the + second input file is not lost (i.e. you can rename @em{-a} to @em{-b} + and @em{-b} to @em{-a} with no problem). + } + li {- + All input files must be unique and all output files must be unique. + Otherwise execution is aborted before making any changes. + } + li {- + In the case that something goes wrong during execution (perhaps you + tried to move a file to a non-existant directory, or a syscall + failed), a backup of your input files is saved automatically by + @code{-mmv} for recovery. + } + } + + p {- + Due to the way @code{-mmv} handles #2, when things do go wrong you may + find that all of your input files have disappeared. Don’t worry though, + @code{-mmv} takes a backup of your code before doing anything. If you + run @code{-mmv} with the @code{--v} option for verbose output, you’ll + notice it backing up your stuff in the @code{-$XDG_CACHE_DIR} directory: + } + + figure { + pre { m4_fmt_code(mmv-verbose.sh.gsp) } + } + + p {- + Upon successful execution the @code{-$XDG_CACHE_DIR/mmv/TIMESTAMP} + directory will be automatically removed, but it remains when things go + wrong so that you can recover any missing data. The names of the + backup-subdirectories in the @code{-$XDG_CACHE_DIR/mmv} directory are + timestamps of when the directories were created. This should make it + easier for you to figure out which directory you need to recover if you + happen to have multiple of these. + } + + h2 #examples {-Examples} + + aside { + p {- + All of these examples are ripped straight from the @code{-mmv(1)} + manual page. If you installed @code{-mmv} through a package manager or + via @code{-make install} then you should have the manual installed on + your system. + } + } + + p {-Swap the files @em{-foo} and @em{-bar}:} + figure { + pre { m4_fmt_code(examples/swap.sh.gsp) } + } + + p {- + Rename all files in the current directory to use hyphens (‘-’) instead + of spaces: + } + figure { + pre { m4_fmt_code(examples/hyphens.sh.gsp) } + } + + p {- + Rename a given list of movies to use lowercase letters and hyphens + instead of uppercase letters and spaces, and number them so that they’re + properly ordered in globs (e.g. rename @em{-The Return of the King.mp4} + to @em{-02-the-return-of-the-king.mp4}): + } + figure { + pre { m4_fmt_code(examples/number.sh.gsp) } + } + + p {- + Rename files interactively in your editor while encoding newline into + the literal string ‘@code{-\\n}’, making use of + @code { + a + href="https://linux.die.net/man/1/vipe" + target="_blank" + {-vipe(1)} + } + from @em{-moreutils}: + } + figure { + pre { m4_fmt_code(examples/vipe.sh.gsp) } + } + + p {- + Rename all C source code- and header files in a git repository + to use snake_case instead of camelCase using + the m4_abbr(GNU) + @code { + a + href="https://www.man7.org/linux/man-pages/man1/sed.1.html" + target="_blank" + {-sed(1)} + } + ‘@code{-\\n}’ extension: + } + figure { + pre { m4_fmt_code(examples/camel-to-snake.sh.gsp) } + } + + p {- + Lowercase all filenames within a directory hierarchy which may contain + newline characters: + } + figure { + pre { m4_fmt_code(examples/lowercase.sh.gsp) } + } + + p {- + Map filenames which may contain newlines in the current directory with + the command ‘@code{-cmd}’, which itself does not support nul-byte + separated entries. This only works assuming your mapping doesn’t + require any context outside of the given input filename (for example, + you would not be able to number your files as this requires knowledge of + the input files position in the input list): + } + figure { + pre { m4_fmt_code(examples/i-flag.sh.gsp) } + } + } + + hr{} + + footer { m4_footer } + } +} diff --git a/src/prj/mmv/index.html b/src/prj/mmv/index.html deleted file mode 100644 index 09aadb1..0000000 --- a/src/prj/mmv/index.html +++ /dev/null @@ -1,667 +0,0 @@ - - - - m4_include(head.html) - - -
-
-

Moving Files the Right Way

- m4_include(nav.html) -
- -
-
-

I think the OpenBSD crowd is a bunch of masturbating - monkeys, in that they make such a big deal about - concentrating on security to the point where they pretty much - admit that nothing else matters to them.

-
-
- Linux Torvalds -
-
-
- -
-

- - You can find the mmv git repository over at - sourcehut - or GitHub. - -

- -

- NOTE: As of the - v1.2.0 release - there is now also the mcp utility. It behaves the same as - the mmv utility but it copies files instead of moving them. - It also doesn’t support the ‘-n’ flag as it doesn’t need to - deal with backups. -

- -

Table of Contents

- - - -

Prologue

-

- File moving and renaming is one of the most common tasks we - undertake on the command-line. We basically always do this with - the mv utility, and it gets the job done most of the - time. Want to rename one file? Use mv! Want to - move a bunch of files into a directory? Use mv! - How could mv ever go wrong? Well I’m glad you asked! -

- -

Advanced Moving and Pitfalls

-

- Let’s start off nice and simple. You just inherited a C project - that uses the sacrilegious - camelCase - naming convention for its files: -

- -
-
m4_fmt_code(ls-files.sh.html)
-
- -

- This deeply upsets you, as it upsets me. So you decide you want - to switch all these files to use - snake_case, - like a normal person. Well how would you do this? You use - mv! This is what you might end up doing: -

- -
-
m4_fmt_code(manual-mv.sh.html)
-
- -

- Well… it works I guess, but it’s a pretty shitty way of renaming - these files. Luckily we only had 5, but what if this was a much - larger project with many more files to rename? Things would get - tedious. So instead we can use a pipeline for - this: -

- -
-
m4_fmt_code(camel-to-snake-naïve.sh.html)
-
- - - -

- That works and it gets the job done, but it’s not really ideal is - it? There are a couple of issues with this. -

- -
    -
  1. -

    - You’re writing more complicated code. This has the - obvious drawback of potentially being more error-prone, - but also risks taking more time to write than you’d like - as you might have forgotten if xargs - actually has an ‘-L’ option or not (which - would require reading the - xargs(1) manual). -

    -
  2. -
  3. -

    - If you try to rename the file foo - to bar but bar already exists, you end - up deleting a file you may not have wanted to. -

    -
  4. -
  5. -

    - In a similar vein to the previous point, you need to be - very careful about schemes like renaming the - file a to b and b - to c. You run the risk of turning a - into c and losing the file b entirely. -

    -
  6. -
  7. -

    - Moving symbolic links is its own whole can of worms. If - a symlink points to a relative location then you need to - make sure you keep pointing to the right place. If the - symlink is absolute however then you can leave it - untouched. But what if the symlink points to a file - that you’re moving as part of your batch move operation? - Now you need to handle that too. -

    -
  8. -
- -

Name Mapping with mmv

- -

- What is mmv? It’s the solution to all your - problems, that’s what it is! mmv takes as its - argument(s) a utility and that utilities arguments and uses that - to create a mapping between old and new filenames — similar to - the map() function found in many programming - languages. I think to best convey how the tool functions, I - should provide an example. Let’s try to do the same thing we did - previously where we tried to turn camelCase files to snake_case, - but using mmv: -

- -
-
m4_fmt_code(camel-to-snake-smart.sh.html)
-
- -

Let me break down how this works.

- -

- mmv starts by reading a series of filenames - separated by newlines from the standard input. Yes, sometimes - filenames have newlines in them and yes there is a way to handle - them but I shall get to that later. The filenames that - mmv reads from the standard input will be referred - to as the input files. Once all the input files have - been read, the utility specified by the arguments is spawned; in - this case that would be sed with the argument - 's/[A-Z]/\L_&/g'. The input files are then piped - into sed the exact same way that they would have - been if we ran the above commands without mmv, and - the output of sed then forms what will be referred - to as the output files. Once a complete list of output - files is accumulated, each input file gets renamed to its - corresponding output file. -

- -

- Let’s look at a simpler example. Say we want to rename 2 files - in the current directory to use lowercase letters, we could use - the following command: -

- -
-
m4_fmt_code(mmv-tr.sh.html)
-
- -

- In the above example mmv reads 2 lines from - standard input, those being LICENSE - and README. Those are our 2 input files now. - The tr utility is then spawned and the input files - are piped into it. We can simulate this in the shell: -

- -
-
m4_fmt_code(tr.sh.html)
-
- -

- As you can see above, tr has produced 2 lines of - output; these are our 2 output files. Since we now have our 2 - input files and 2 output files, mmv can go ahead - and rename the files. In this case it will rename - LICENSE to license and - README to readme. For some examples, check - the examples section of this page down - below. -

- -

Filenames with Embedded Newlines

- -

- People are retarded, and as a result we have filenames with - newlines in them. All it would have taken to solve this issue - for everyone was for literally anybody during - the early UNIX days to go “hey, this is a bad idea!”, - but alas, we must deal with this. Newlines are of course not - the only special characters filenames can contain, but they are - the single most infuriating to deal with; the UNIX utilities all - being line-oriented really doesn’t work well with these files. -

- -

- So how does mmv deal with special characters, and - newlines in particular? Well it does so by providing the user - with the -0 and -e flags: -

- -
-
-0
-
-

- Tell mmv to expect its input to not be - separated by newlines (‘\n’), but by NUL - bytes (‘\0’). NUL bytes are the only - characters not allowed in filenames besides forward - slashes, so they are an obvious choice for an - alternative separator. -

-
-
-e
-
-

- Encode newlines in filenames before passing them to the - provided utility. Newline characters are replaced by the - literal string ‘\n’ and backslashes by the - literal string ‘\\’. After processing, the - resulting output is decoded again. -

-

- If combined with the -0 flag, then while - input will be read assuming a NUL-byte input-seperator, - the encoded input files will be written to the spawned - process newline-seperated. -

-
-
- -

The Simple Case

- -

- In order to better understand these flags and how they work - let’s go though another example. We have 2 files — one with and - one without an embedded newline — and our goal is to simply - reverse these filenames. In this example I am going to be - displaying newlines in filenames with the “$'\n'” - syntax as this is how my shell displays embedded newlines. -

- -

- We can start by just trying to naïvely pass these 2 files - to mmv and use rev to reverse the - names, but this doesn’t work: -

- -
-
m4_fmt_code(mmv-rev.sh.html)
-
- -

- The reason this doesn’t work is because due to the line-oriented - nature of ls and rev, we are actually - trying to rename the files foo, bar, and - baz to the new filenames zab, - rab, and oof. As can be seen in the following - diagram, the embedded newline is causing our input to be ambiguous - and mmv can’t reliably proceed - anymore 1: -

- -
- -
- - - -

- The first thing we need to do in order to proceed is to pass - the -0 flag to mmv. This will - tell mmv that we want to use the NUL-byte as our - input separator and not the newline. We also need ls - to actually provide us with the filenames delimited by NUL-bytes. - Luckily GNU ls gives us the - --zero flag to do just that: -

- -
-
m4_fmt_code(mmv-rev-zero.sh.html)
-
- -

- So we’re getting places, but we aren’t quite there yet. The - issue we’re getting now is that mmv recieved 2 - input files from the standard input, but rev - produced 3 output files. Why is that? Well let’s try our hand - at a little bit of command-line debugging with sed: -

- -
-
m4_fmt_code(sed-debugging.sh.html)
-
- -

- If you aren’t quite sure what the above is doing, here’s a quick - summary: -

- - - -

- In the sed output, we can see that $ - represents the end of a line, and \000 represents - the NUL-byte. All looks good here, we have two inputs seperated - by NUL-bytes. Now let’s try to throw in rev: -

- -
-
m4_fmt_code(sed-debugging-rev.sh.html)
-
- -

- Well wouldn’t you know it? Since rev also - works with newline-seperated input, it reversed out NUL-byte - seperators and now gives us 3 outputs. Luckily the folks over - at util-linux provided us with the -0 flag - here too, so that we can properly handle NUL-delimited input. - Combining all of this together we get a final working product: -

- -
-
m4_fmt_code(reverse-embedded-newline.sh.html)
-
- -

Encoding Newlines

- -

- Sometimes we want to rename a bunch of files, but the command we - want to use doesn’t support NUL-bytes as nicely as we would - like. In these cases, you may want to consider encoding your - newline characters into the literal string ‘\n’ and - then passing your input newline-seperated to your given command - with the -e flag. -

- -

- For a real-world example, perhaps you want to edit some - filenames in vim, or whatever other editor you use. Well we can - do this incredibly easily with the vipe utility - from - the moreutils - collection. The vipe command simply reads input - from the standard input, opens it up in your editor, and then - prints the resulting output to the standard output; perfect - for mmv! We do not really want to deal with - NUL-bytes in our text-editor though, so let’s just encode our - newlines: -

- -
-
m4_fmt_code(vipe.sh.html)
-
- - - -

- When running the above code example, you will see the following - in your editor: -

- -
-
m4_fmt_code(vim.html)
-
- -

- After you exit your editor, mmv will decode all - occurances of ‘\n’ back into a newline, and all - occurances of ‘\\’ back into a backslash: -

- -
- -
- -

Individual Execution

-

- The previous examples are great and all, but what do you do if - your mapping command doesn’t have the concept of an input - seperator at all? This is where the -i flag comes - into play. With the -i flag we can - get mmv to execute our mapping command for every - input filename. This means that as long as we can work with a - complete buffer, we don’t need to worry about seperators. -

- -

- To be honest, I cannot really think of any situation where you - might actually need to do this. If you can think of one, - please email me and - I’ll update the example on this page. Regardless, let’s imagine - that we wanted to rename some files so that their filenames are - replaced with their filename - - SHA-1 hash. - On Linux we have the sha1sum program which reads - input from the standard input and outputs the SHA-1 hash. This - is how we would use it with mmv: -

- -
-
m4_fmt_code(sha1sum-long-example.sh.html)
-
- -

- Another approach is to invoke mmv twice: -

- -
-
m4_fmt_code(sha1sum-short-example.sh.html)
-
- -

- If you are confused about why we need to make a call - to awk, it’s because the sha1sum - program outputs 2 columns of data. The first column is our hash - and the second column is the filename where the to-be-hashed - data was read from. We don’t want the second column. -

- -

- Unlike in previous examples where one process was spawned to map - all our filenames, with the -i flag we are spawning - a new instance for each filename. If you struggle to visualize - this, perhaps the following diagrams help: -

- -
-
Invoking mmv without -i
- -
- -
-
Invoking mmv with -i
- -
- -

Safety

-

- When compared to the standard for f in *; do mv $f …; - done or ls | … | xargs -L2 mv - constructs, mmv is significantly more safe to use. - These are some of the safety features that are built into the - tool: -

- -
    -
  1. - If the number of input- and output files differs, execution - is aborted before making any changes. -
  2. -
  3. - If an input file is renamed to the name of another input - file, the second input file is not lost (i.e. you can rename - a to b and b to a with - no problem). -
  4. -
  5. - All input files must be unique and all output files must be - unique. Otherwise execution is aborted before making any - changes. -
  6. -
  7. - In the case that something goes wrong during execution - (perhaps you tried to move a file to a non-existant - directory, or a syscall failed), a backup of your input - files is saved automatically by mmv for - recovery. -
  8. -
- -

- Due to the way mmv handles #2, when things do go - wrong you may find that all of your input files have - disappeared. Don’t worry though, mmv takes a - backup of your code before doing anything. If you - run mmv with the -v option for verbose - output, you’ll notice it backing up your stuff in - the $XDG_CACHE_DIR directory: -

- -
-
m4_fmt_code(mmv-verbose.sh.html)
-
- -

- Upon successful execution - the $XDG_CACHE_DIR/mmv/TIMESTAMP directory will be - automatically removed, but it remains when things go wrong so - that you can recover any missing data. The names of the - backup-subdirectories in the $XDG_CACHE_DIR/mmv - directory are timestamps of when the directories were created. - This should make it easier for you to figure out which directory - you need to recover if you happen to have multiple of these. -

- -

Examples

- - - -

Swap the files foo and bar:

-
-
m4_fmt_code(examples/swap.sh.html)
-
- -

- Rename all files in the current directory to use hyphens (‘-’) - instead of spaces: -

-
-
m4_fmt_code(examples/hyphens.sh.html)
-
- -

- Rename a given list of movies to use lowercase letters and - hyphens instead of uppercase letters and spaces, and number them - so that they’re properly ordered in globs (e.g. rename The - Return of the King.mp4 to - 02-the-return-of-the-king.mp4): -

-
-
m4_fmt_code(examples/number.sh.html)
-
- -

- Rename files interactively in your editor while encoding newline - into the literal string ‘\n’, making use - of vipe(1) from moreutils: -

-
-
m4_fmt_code(examples/vipe.sh.html)
-
- -

- Rename all C source code- and header files in a git repository - to use snake_case instead of camelCase using - the GNU - sed(1)\n’ extension: -

-
-
m4_fmt_code(examples/camel-to-snake.sh.html)
-
- -

- Lowercase all filenames within a directory hierarchy which may - contain newline characters: -

-
-
m4_fmt_code(examples/lowercase.sh.html)
-
- -

- Map filenames which may contain newlines in the current - directory with the command ‘cmd’, which itself does - not support nul-byte separated entries. This only works - assuming your mapping doesn’t require any context outside of the - given input filename (for example, you would not be able to - number your files as this requires knowledge of the input files - position in the input list): -

-
-
m4_fmt_code(examples/i-flag.sh.html)
-
-
- -
- - - - diff --git a/src/prj/mmv/ls-files.sh.gsp b/src/prj/mmv/ls-files.sh.gsp new file mode 100644 index 0000000..95e6af3 --- /dev/null +++ b/src/prj/mmv/ls-files.sh.gsp @@ -0,0 +1,2 @@ +$ @span .sh-fn {-ls} +bytecodeVm.c fastLexer.c fastLexer.h slowParser.c slowParser.h diff --git a/src/prj/mmv/ls-files.sh.html b/src/prj/mmv/ls-files.sh.html deleted file mode 100644 index d24b5af..0000000 --- a/src/prj/mmv/ls-files.sh.html +++ /dev/null @@ -1,2 +0,0 @@ -$ ls -bytecodeVm.c fastLexer.c fastLexer.h slowParser.c slowParser.h diff --git a/src/prj/mmv/manual-mv.sh.gsp b/src/prj/mmv/manual-mv.sh.gsp new file mode 100644 index 0000000..0dbc3e5 --- /dev/null +++ b/src/prj/mmv/manual-mv.sh.gsp @@ -0,0 +1,5 @@ +$ @span .sh-fn {-mv} bytecodeVm.c bytecode_vm.c +$ @span .sh-fn {-mv} fastLexer.c fast_lexer.c +$ @span .sh-fn {-mv} fastLexer.h fast_lexer.h +$ @span .sh-fn {-mv} slowParser.c slow_parser.c +$ @span .sh-fn {-mv} slowParser.h slow_parser.h diff --git a/src/prj/mmv/manual-mv.sh.html b/src/prj/mmv/manual-mv.sh.html deleted file mode 100644 index 2484d9f..0000000 --- a/src/prj/mmv/manual-mv.sh.html +++ /dev/null @@ -1,5 +0,0 @@ -$ mv bytecodeVm.c bytecode_vm.c -$ mv fastLexer.c fast_lexer.c -$ mv fastLexer.h fast_lexer.h -$ mv slowParser.c slow_parser.c -$ mv slowParser.h slow_parser.h diff --git a/src/prj/mmv/mmv-rev-zero.sh.gsp b/src/prj/mmv/mmv-rev-zero.sh.gsp new file mode 100644 index 0000000..ef8d158 --- /dev/null +++ b/src/prj/mmv/mmv-rev-zero.sh.gsp @@ -0,0 +1,2 @@ +$ @span .sh-fn {-ls} --zero foo$'\\n'bar baz | @span .sh-fn {-mmv} -0 rev +mmv: Files have been added or removed during editing diff --git a/src/prj/mmv/mmv-rev-zero.sh.html b/src/prj/mmv/mmv-rev-zero.sh.html deleted file mode 100644 index 4be992e..0000000 --- a/src/prj/mmv/mmv-rev-zero.sh.html +++ /dev/null @@ -1,2 +0,0 @@ -$ ls --zero foo$'\n'bar baz | mmv -0 rev -mmv: Files have been added or removed during editing diff --git a/src/prj/mmv/mmv-rev.sh.gsp b/src/prj/mmv/mmv-rev.sh.gsp new file mode 100644 index 0000000..e2e6a1c --- /dev/null +++ b/src/prj/mmv/mmv-rev.sh.gsp @@ -0,0 +1,2 @@ +$ @span .sh-fn {-ls} foo$'\\n'bar baz | @span .sh-fn {-mmv} rev +mmv: No such file or directory (os error 2) diff --git a/src/prj/mmv/mmv-rev.sh.html b/src/prj/mmv/mmv-rev.sh.html deleted file mode 100644 index 3d2e683..0000000 --- a/src/prj/mmv/mmv-rev.sh.html +++ /dev/null @@ -1,2 +0,0 @@ -$ ls foo$'\n'bar baz | mmv rev -mmv: No such file or directory (os error 2) diff --git a/src/prj/mmv/mmv-tr.sh.gsp b/src/prj/mmv/mmv-tr.sh.gsp new file mode 100644 index 0000000..83a728b --- /dev/null +++ b/src/prj/mmv/mmv-tr.sh.gsp @@ -0,0 +1 @@ +$ @span .sh-fn {-ls} LICENSE README | @span .sh-fn {-mmv} tr A-Z a-z diff --git a/src/prj/mmv/mmv-tr.sh.html b/src/prj/mmv/mmv-tr.sh.html deleted file mode 100644 index 4d8773a..0000000 --- a/src/prj/mmv/mmv-tr.sh.html +++ /dev/null @@ -1 +0,0 @@ -$ ls LICENSE README | mmv tr A-Z a-z diff --git a/src/prj/mmv/mmv-verbose.sh.gsp b/src/prj/mmv/mmv-verbose.sh.gsp new file mode 100644 index 0000000..dc4dfa0 --- /dev/null +++ b/src/prj/mmv/mmv-verbose.sh.gsp @@ -0,0 +1,8 @@ +$ @span .sh-fn {-ls} foo bar | @span .sh-fn {-mmv} -v awk @span .sh-str {-'{ printf "%d-%s\\n", NR, $0 \}'} +… +created directory ‘/home/thomas/.cache/mmv/1692102229’ +created directory ‘/home/thomas/.cache/mmv/1692102229/home/thomas/code/repo/Mango0x45/mmv’ +copied ‘/home/thomas/code/repo/Mango0x45/mmv/bar’ -> ‘/home/thomas/.cache/mmv/1692102229/home/thomas/code/repo/Mango0x45/mmv/bar’ +created directory ‘/home/thomas/.cache/mmv/1692102229/home/thomas/code/repo/Mango0x45/mmv’ +copied ‘/home/thomas/code/repo/Mango0x45/mmv/foo’ -> ‘/home/thomas/.cache/mmv/1692102229/home/thomas/code/repo/Mango0x45/mmv/foo’ +… diff --git a/src/prj/mmv/mmv-verbose.sh.html b/src/prj/mmv/mmv-verbose.sh.html deleted file mode 100644 index 3767416..0000000 --- a/src/prj/mmv/mmv-verbose.sh.html +++ /dev/null @@ -1,8 +0,0 @@ -$ ls foo bar | mmv -v awk '{ printf "%d-%s\n", NR, $0 }' -… -created directory ‘/home/thomas/.cache/mmv/1692102229’ -created directory ‘/home/thomas/.cache/mmv/1692102229/home/thomas/code/repo/Mango0x45/mmv’ -copied ‘/home/thomas/code/repo/Mango0x45/mmv/bar’ -> ‘/home/thomas/.cache/mmv/1692102229/home/thomas/code/repo/Mango0x45/mmv/bar’ -created directory ‘/home/thomas/.cache/mmv/1692102229/home/thomas/code/repo/Mango0x45/mmv’ -copied ‘/home/thomas/code/repo/Mango0x45/mmv/foo’ -> ‘/home/thomas/.cache/mmv/1692102229/home/thomas/code/repo/Mango0x45/mmv/foo’ -… diff --git a/src/prj/mmv/reverse-embedded-newline.sh.gsp b/src/prj/mmv/reverse-embedded-newline.sh.gsp new file mode 100644 index 0000000..3a91d08 --- /dev/null +++ b/src/prj/mmv/reverse-embedded-newline.sh.gsp @@ -0,0 +1,3 @@ +$ @span .sh-fn {-ls} --zero foo$'\\n'bar baz | @span .sh-fn {-mmv} -0 rev -0 +$ @span .sh-fn {-ls} +'rab'$'\\n''oof' zab diff --git a/src/prj/mmv/reverse-embedded-newline.sh.html b/src/prj/mmv/reverse-embedded-newline.sh.html deleted file mode 100644 index ff84d5c..0000000 --- a/src/prj/mmv/reverse-embedded-newline.sh.html +++ /dev/null @@ -1,3 +0,0 @@ -$ ls --zero foo$'\n'bar baz | mmv -0 rev -0 -$ ls -'rab'$'\n''oof' zab diff --git a/src/prj/mmv/sed-debugging-rev.sh.gsp b/src/prj/mmv/sed-debugging-rev.sh.gsp new file mode 100644 index 0000000..39b7c5a --- /dev/null +++ b/src/prj/mmv/sed-debugging-rev.sh.gsp @@ -0,0 +1,3 @@ +$ @span .sh-fn {-ls} -U --zero foo$'\\n'bar baz | @span .sh-fn {-rev} | @span .sh-fn {-sed} -n l +oof$ +\\000zab\\000rab$ diff --git a/src/prj/mmv/sed-debugging-rev.sh.html b/src/prj/mmv/sed-debugging-rev.sh.html deleted file mode 100644 index f1fddb1..0000000 --- a/src/prj/mmv/sed-debugging-rev.sh.html +++ /dev/null @@ -1,3 +0,0 @@ -$ ls -U --zero foo$'\n'bar baz | rev | sed -n l -oof$ -\000zab\000rab$ diff --git a/src/prj/mmv/sed-debugging.sh.gsp b/src/prj/mmv/sed-debugging.sh.gsp new file mode 100644 index 0000000..3db277f --- /dev/null +++ b/src/prj/mmv/sed-debugging.sh.gsp @@ -0,0 +1,3 @@ +$ @span .sh-fn {-ls} -U --zero foo$'\\n'bar baz | @span .sh-fn {-sed} -n l +foo$ +bar\\000baz\\000$ diff --git a/src/prj/mmv/sed-debugging.sh.html b/src/prj/mmv/sed-debugging.sh.html deleted file mode 100644 index e61cde4..0000000 --- a/src/prj/mmv/sed-debugging.sh.html +++ /dev/null @@ -1,3 +0,0 @@ -$ ls -U --zero foo$'\n'bar baz | sed -n l -foo$ -bar\000baz\000$ diff --git a/src/prj/mmv/sha1sum-long-example.sh.gsp b/src/prj/mmv/sha1sum-long-example.sh.gsp new file mode 100644 index 0000000..f997509 --- /dev/null +++ b/src/prj/mmv/sha1sum-long-example.sh.gsp @@ -0,0 +1,11 @@ +$ @span .sh-fn {-touch} foo bar +$ @span .sh-fn {-cat} <<@span .sh-hd {-EOF} >hash-filename +@span .sh-hd {-#!/bin/sh} + +@span .sh-hd {-sha1sum | awk '{ print \\$1 \}'} +@span .sh-hd {-EOF} +$ @span .sh-fn {-chmod} +x hash-filename +$ @span .sh-fn {-ls} foo bar | @span .sh-fn {-mmv} -i ./hash-filename +$ @span .sh-fn {-ls} +e242ed3bffccdf271b7fbaf34ed72d089537b42f hash-filename +f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 diff --git a/src/prj/mmv/sha1sum-long-example.sh.html b/src/prj/mmv/sha1sum-long-example.sh.html deleted file mode 100644 index ddbda86..0000000 --- a/src/prj/mmv/sha1sum-long-example.sh.html +++ /dev/null @@ -1,11 +0,0 @@ -$ touch foo bar -$ cat <<EOF >hash-filename -#!/bin/sh - -sha1sum | awk '{ print \$1 }' -EOF -$ chmod +x hash-filename -$ ls foo bar | mmv -i ./hash-filename -$ ls -e242ed3bffccdf271b7fbaf34ed72d089537b42f hash-filename -f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 diff --git a/src/prj/mmv/sha1sum-short-example.sh.gsp b/src/prj/mmv/sha1sum-short-example.sh.gsp new file mode 100644 index 0000000..0811dde --- /dev/null +++ b/src/prj/mmv/sha1sum-short-example.sh.gsp @@ -0,0 +1,6 @@ +$ @span .sh-fn {-touch} foo bar +$ @span .sh-fn {-ls} | @span .sh-fn {-mmv} -i sha1sum +$ @span .sh-fn {-ls} | @span .sh-fn {-mmv} awk @span .sh-str {-'{ print $1 \}'} +$ @span .sh-fn {-ls} +e242ed3bffccdf271b7fbaf34ed72d089537b42f +f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 diff --git a/src/prj/mmv/sha1sum-short-example.sh.html b/src/prj/mmv/sha1sum-short-example.sh.html deleted file mode 100644 index 99e781c..0000000 --- a/src/prj/mmv/sha1sum-short-example.sh.html +++ /dev/null @@ -1,6 +0,0 @@ -$ touch foo bar -$ ls | mmv -i sha1sum -$ ls | mmv awk '{ print $1 }' -$ ls -e242ed3bffccdf271b7fbaf34ed72d089537b42f -f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 diff --git a/src/prj/mmv/tr.sh.gsp b/src/prj/mmv/tr.sh.gsp new file mode 100644 index 0000000..e357de8 --- /dev/null +++ b/src/prj/mmv/tr.sh.gsp @@ -0,0 +1,3 @@ +$ @span .sh-fn {-ls} LICENSE README | @span .sh-fn {-tr} A-Z a-z +license +readme diff --git a/src/prj/mmv/tr.sh.html b/src/prj/mmv/tr.sh.html deleted file mode 100644 index db08c38..0000000 --- a/src/prj/mmv/tr.sh.html +++ /dev/null @@ -1,3 +0,0 @@ -$ ls LICENSE README | tr A-Z a-z -license -readme diff --git a/src/prj/mmv/vim.gsp b/src/prj/mmv/vim.gsp new file mode 100644 index 0000000..1c20dca --- /dev/null +++ b/src/prj/mmv/vim.gsp @@ -0,0 +1,2 @@ +foo\\nbar +baz diff --git a/src/prj/mmv/vim.html b/src/prj/mmv/vim.html deleted file mode 100644 index cd89cd8..0000000 --- a/src/prj/mmv/vim.html +++ /dev/null @@ -1,2 +0,0 @@ -foo\nbar -baz diff --git a/src/prj/mmv/vipe.sh.gsp b/src/prj/mmv/vipe.sh.gsp new file mode 100644 index 0000000..690db73 --- /dev/null +++ b/src/prj/mmv/vipe.sh.gsp @@ -0,0 +1 @@ +$ @span .sh-fn {-ls} --zero foo$'\\n'bar baz | @span .sh-fn {-mmv} -0e vipe diff --git a/src/prj/mmv/vipe.sh.html b/src/prj/mmv/vipe.sh.html deleted file mode 100644 index c56ff08..0000000 --- a/src/prj/mmv/vipe.sh.html +++ /dev/null @@ -1 +0,0 @@ -$ ls --zero foo$'\n'bar baz | mmv -0e vipe diff --git a/src/prj/totp/basic-usage.sh.gsp b/src/prj/totp/basic-usage.sh.gsp new file mode 100644 index 0000000..f1afa3f --- /dev/null +++ b/src/prj/totp/basic-usage.sh.gsp @@ -0,0 +1,7 @@ +$ @span .sh-var {-code}=@span .sh-ex {-`mkpass A-Z0-7`} +$ @span .sh-fn {-totp} $@span .sh-var {-code} +475867 +$ @span .sh-fn {-echo} $@span .sh-var {-code} | @span .sh-fn {-totp} +475867 +$ @span .sh-fn {-totp} -d 10 $@span .sh-var {-code} +0718732338 diff --git a/src/prj/totp/basic-usage.sh.html b/src/prj/totp/basic-usage.sh.html deleted file mode 100644 index 9023218..0000000 --- a/src/prj/totp/basic-usage.sh.html +++ /dev/null @@ -1,7 +0,0 @@ -$ code=`mkpass A-Z0-7` -$ totp $code -475867 -$ echo $code | totp -475867 -$ totp -d 10 $code -0718732338 diff --git a/src/prj/totp/index.gsp b/src/prj/totp/index.gsp new file mode 100644 index 0000000..ea5637a --- /dev/null +++ b/src/prj/totp/index.gsp @@ -0,0 +1,134 @@ +html lang="en" { + head { m4_include(head.gsp) } + body { + header { + div { + h1 {-Easy Password Generation} + m4_include(nav.gsp) + } + + figure .quote { + blockquote { + p {= + The C preprocessor is worse than m4, and I would kill myself before I + had to use m4. + } + } + figcaption {-Arav K.} + } + } + + main { + p { + em {- + You can find the @code{-totp} git repository over at + @a href="https://git.sr.ht/~mango/totp" target="_blank" {-sourcehut} + or + @a href="https://github.com/Mango0x45/totp" target="_blank" {-GitHub}. + } + } + + h2 {-Table of Contents} + ul { + li {a href="#prologue" {-Prologue}} + li {a href="#terms" {-Terminology}} + li {a href="#usage" {-Basic Usage}} + li {a href="#qr" {-Working with QR Codes}} + } + + h2 #prologue {-Prologue} + p {- + m4_abbr(TOTP) codes are pretty cool, and really easay to do. They’re + also the backbone of modern two-factor authentication. With + @code{-totp} I hope to handling m4_abbr(TOTP) codes as easy and + extensible as possible + } + + h2 #terms {-Terminology} + p {- + There are a few terms that I will be using throughout this post, so it’s + good to make sure that we’re all on the same page about what I’m + referring to. + } + + dl { + dt {-Secret} + dd { + p {- + Your @em{-secret} is a + @a + href="https://en.wikipedia.org/wiki/Base32" + target="_blank" + {-base32} + encoded secret key that you should under no circumstances share with + anyone else. It is from this secret key that we can generate valid + m4_abbr(TOTP) codes. + } + } + + dt {-Digits} + dd { + p {- + Your @em {-digits} is the length of the generated m4_abbr(TOTP) in + digits. If @em{-digits} is 8, then your generated key could be + ‘01234567’. When dealing with m4_abbr(2FA) this is typically 6. + } + } + + dt {-Period} + dd { + p {- + Your @em{-period} it the duration for which the generated key is + valid in seconds. When working with m4_abbr(2FA) this is typically + 30. + } + } + } + + h2 #usage {-Basic Usage} + + p {- + @code{-totp} takes secret keys as command-line arguments, but also reads + them from the standard input if none are provided. It assumes that + @em{-digits} is 6 and @em{-period} is 30. These defaults can be changed + with the @code{--d} and @code{--p} flags. + } + + figure { + pre { m4_fmt_code(basic-usage.sh.gsp) } + } + + aside { + p {- + I’m using @code{-mkpass} to generate a random secret. You can + see my post about @code{-mkpass} @a href="/prj/mkpass" {-here}. + } + } + + h2 #qr {-Working with m4_abbr(QR) Codes} + p {- + Often times when enabling m4_abbr(2FA) on your account on some website + or platform, you will be shown a m4_abbr(QR) code you can scan with your + m4_abbr(2FA) mobile application. These m4_abbr(QR) codes contain + @em{-otpauth} m4_abbr(URI)s. We can extract these from downloaded + images using utilities such as @code{-zbarimg} and use them in + @code{-totp} using the @code{--u} flag to enable ‘m4_abbr(URI) mode’ + } + + figure { + pre { m4_fmt_code(zbarimg.sh.gsp) } + } + + p {- + …and that’s all! There’s nothing else you need. You can use secret + keys and otpauth m4_abbr(URI)s, and you can configure the @em{-digits} + and @em{-period} of the generated codes. You can generate multiple keys + at once, and all outputs are printed to the standard output. + } + } + + hr{} + + footer { m4_footer } + } +} diff --git a/src/prj/totp/index.html b/src/prj/totp/index.html deleted file mode 100644 index aa040d4..0000000 --- a/src/prj/totp/index.html +++ /dev/null @@ -1,140 +0,0 @@ - - - - m4_include(head.html) - - -
-
-

Easy Password Generation

- m4_include(nav.html) -
- -
-
-

The C preprocessor is worse than m4, and I would kill myself - before I had to use m4.

-
-
- Arav K. -
-
-
- -
-

- - You can find the totp git repository over at - sourcehut - or GitHub. - -

- -

Table of Contents

- - - -

Prologue

-

- TOTP codes are pretty cool, and really easy to - do. They’re also the backbone of modern two-factor authentication. - With totp I hope to make - handling TOTP codes as easy and extensible as - possible. -

- -

Terminology

-

- There are a few terms that I will be using throughout this post, so it’s - good to make sure that we’re all on the same page about what I’m - referring to. -

- -
-
Secret
-
-

- Your secret is - a base32 encoded secret key that you should under - no circumstances share with anyone else. It is from this secret key - that we can generate valid TOTP codes. -

-
- -
Digits
-
-

- Your digits is the length of the generated - TOTP in digits. If digits is 8, - then your generated key could be ‘01234567’. When dealing - with 2FA this is typically 6. -

-
- -
Period
-
-

- Your period it the duration for which the generated key is - valid in seconds. When working with 2FA - this is typically 30. -

-
-
- -

Basic Usage

-

- totp takes secret keys as command-line arguments, but also - reads them from the standard input if none are provided. It assumes - that digits is 6 and period is 30. These defaults can - be changed with the -d and -p flags. -

- -
-
m4_fmt_code(basic-usage.sh.html)
-
- - - -

Working with QR Codes

-

- Often times when enabling 2FA on your account - on some website or platform, you will be shown - a QR code you can scan with - your 2FA mobile application. - These QR codes - contain otpauth URIs. We can extract - these from downloaded images using utilities such - as zbarimg and use them in totp using - the -u flag to enable ‘URI mode’ -

- -
-
m4_fmt_code(zbarimg.sh.html)
-
- - …and that’s all! There’s nothing else you need. You can use secret keys - and otpauth URIs, and you can configure - the digits and period of the generated codes. You can - generate multiple keys at once, and all outputs are printed to the - standard output. -
- -
- - - - diff --git a/src/prj/totp/zbarimg.sh.gsp b/src/prj/totp/zbarimg.sh.gsp new file mode 100644 index 0000000..cd0669b --- /dev/null +++ b/src/prj/totp/zbarimg.sh.gsp @@ -0,0 +1,4 @@ +$ @span .sh-fn {-zbarimg} -q my-qr-code.svg @span .sh-cmt {-# Also works with jpg, png, etc.} +QR-Code:otpauth://totp/GitHub:Mango0x45?secret=O1AIWMONKWVRJY4H&issuer=GitHub +$ @span .sh-fn {-zbarimg} -q my-qr-code.svg | @span .sh-fn {-sed} s/QR-Code:// | @span .sh-fn {-totp} -u +554210 diff --git a/src/prj/totp/zbarimg.sh.html b/src/prj/totp/zbarimg.sh.html deleted file mode 100644 index 862eb78..0000000 --- a/src/prj/totp/zbarimg.sh.html +++ /dev/null @@ -1,4 +0,0 @@ -$ zbarimg -q my-qr-code.svg # Also works with jpg, png, etc. -QR-Code:otpauth://totp/GitHub:Mango0x45?secret=O1AIWMONKWVRJY4H&issuer=GitHub -$ zbarimg -q my-qr-code.svg | sed s/QR-Code:// | totp -u -554210 -- cgit v1.2.3