diff options
author | Thomas Voss <mail@thomasvoss.com> | 2023-09-11 05:15:20 +0200 |
---|---|---|
committer | Thomas Voss <mail@thomasvoss.com> | 2023-09-11 05:15:20 +0200 |
commit | bda44e93541fa478abf3ce4b3461f026a90fa8cb (patch) | |
tree | a62a7e1d456effe914a77b45f66485c3e8bfd92d /src | |
parent | ced3ed9ddde25614bbc9777a5d546eee2a44a2e0 (diff) |
Move the site from HTML to GSP
Diffstat (limited to 'src')
81 files changed, 1711 insertions, 1801 deletions
diff --git a/src/ame/index.gsp b/src/ame/index.gsp new file mode 100644 index 0000000..e0ed55b --- /dev/null +++ b/src/ame/index.gsp @@ -0,0 +1,92 @@ +html lang="en" { + head { m4_include(head.gsp) } + body { + header { + div { + h1 {-About Me} + m4_include(nav.gsp) + } + + figure .quote { + blockquote { + p {= + One obvious advantage [of lisp syntax] is that there hardly *is* any + syntax. You can learn enough Lisp syntax to write useful programs + in about ten minutes. + } + } + figcaption {-Mark J. Dominus} + } + } + + main { + p {- + If you are a prospective employer, you can view my m4_abbr(CV) + @a href="https://cv.thomasvoss.com" target="_blank" {-here}. + } + + h2 {-Who Am I} + + p {- + I’m Thomas. A self-taught software developer from Brazil and the + Netherlands who grew up in the Middle East. I started to code at the + age of 9, writing batch scripts @x-ref {-1} on my schools Windows 7 + machines to toggle folder visibility with a password. That became + necessary because the genius m4_abbr(IT) guys at our school decided we + should all save our work onto a shared m4_abbr(NAS) where everyone has + read+write access to everyone elses work. @em {-How could that ever go + wrong.} + } + + aside { + p data-ref="1" {- + Shoutouts to + @a + href="https://www.instructables.com/member/Prof.%20Pickle/" + target="_blank" + {- + Prof. Pickle on Instructables + } + by the way. Most of his stuff seems to have been deleted all these + years later, but he was the guy I learnt to code from. + } + } + + p {- + These days my interests lie mostly in m4_abbr(CLI) development. I take + a great joy in writing simple yet highly effective tools to solve + problems not only in the easiest way, but also in the most extensible + way possible. I think my batch file-renaming utility @em {-mmv} + @a href="/prj/mmv" {-does a great job at that}. + } + + p {- + That being said, I also have a great interest in operating systems, + shells, and really anything that could be considered remotely low-level. + I’m not totally afraid of front-end development, although I @em {-did} + write this site in plain m4_abbr(HTML) and m4_abbr(CSS) because modern + m4_abbr(HTML) frameworks are the worst excuses for software I have ever + seen. + } + + p {- + As for my religious- and political beliefs, let’s make those + clear: + @ul { + li {-Spaces should never be used for indentation} + li {-Tabs should never be used for alignment} + li {-Emacs is better than Vim} + li {-The dominance of VSCode is an embarrassment to our industry} + li {- + Object-oriented programming, Java, JavaScript, and m4_abbr(XML) were + all massive mistakes + } + li {-C is far superior to C++} + li {-Rust is not gods chosen language (even if it’s pretty cool)} + } + } + } + + footer { m4_footer } + } +} diff --git a/src/ame/index.html b/src/ame/index.html deleted file mode 100644 index 20ebacd..0000000 --- a/src/ame/index.html +++ /dev/null @@ -1,105 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - m4_include(head.html) - </head> - <body> - <header> - <div> - <h1>About Me</h1> - m4_include(nav.html) - </div> - - <figure class="quote"> - <blockquote> - <p>One obvious advantage [of lisp syntax] is that there - hardly *is* any syntax. You can learn enough Lisp - syntax to write useful programs in about ten minutes.</p> - </blockquote> - <figcaption> - Mark J. Dominus - </figcaption> - </figure> - </header> - - <main> - <p> - If you are a prospective employer, you can view - my <abbr class="cv">CV</abbr> - <a href="https://cv.thomasvoss.com" target="_blank">here</a>. - </p> - - <h2>Who Am I</h2> - - <p> - I’m Thomas. A self-taught software developer from Brazil and - the Netherlands who grew up in the Middle East. I started to - code at the age of 9, writing batch scripts <x-ref>1</x-ref> on - my schools Windows 7 machines to toggle folder visibility with a - password. That became necessary because the - genius <abbr class="it">IT</abbr> guys at our school decided we - should all save our work onto a - shared <abbr class="nas">NAS</abbr> where everyone has - read+write access to everyone elses work. <em>How could that - ever go wrong.</em> - </p> - - <aside> - <p data-ref="1"> - Shoutouts - to <a href="https://www.instructables.com/member/Prof.%20Pickle/" - target="_blank">Prof. Pickle on Instructables</a> by the - way. Most of his stuff seems to have been deleted all these - years later, but he was the guy I learnt to code from. - </p> - </aside> - - <p> - These days my interests lie mostly - in <abbr class="cli">CLI</abbr> development. I take a great joy - in writing simple yet highly effective tools to solve problems - not only in the easiest way, but also in the most extensible way - possible. I think my batch file-renaming - utility <em>mmv</em> <a href="/prj/mmv">does a great job at - that</a>. - </p> - - <p> - That being said, I also have a great interest in operating - systems, shells, and really anything that could be considered - remotely low-level. I’m not totally afraid of front-end - development, although I <em>did</em> write this site in plain - <abbr class="html">HTML</abbr> and <abbr class="css">CSS</abbr> - because modern <abbr class="html">HTML</abbr> frameworks are the - worst excuses for software I have ever seen. - </p> - - <p> - As for my religious- and political beliefs, let’s make those - clear: - <ul> - <li>Spaces should never be used for indentation</li> - <li>Tabs should never be used for alignment</li> - <li>Emacs is better than Vim</li> - <li> - The dominance of VSCode is an embarrassment to our - industry - </li> - <li> - Object-oriented programming, Java, JavaScript, - and <abbr class="xml">XML</abbr> were all massive - mistakes - </li> - <li>C is far superior to C++</li> - <li>Rust is not gods chosen language (even if it’s pretty cool)</li> - </ul> - </p> - </main> - - <hr> - - <footer> - m4_footer - </footer> - </body> -</html> diff --git a/src/index.gsp b/src/index.gsp new file mode 100644 index 0000000..9f2808c --- /dev/null +++ b/src/index.gsp @@ -0,0 +1,55 @@ +html lang="en" { + head { m4_include(head.gsp) } + body { + header { + h1 {-Root Page} + + figure .quote { + blockquote { + p {= + If Java had true garbage collection, most programs would delete + themselves upon execution. + } + } + figcaption {-Robert Sewell} + } + } + + main { + p {- + Welcome to my plot of the internet. This site is mostly oriented + towards topics related to software development, but you might eventually + find some things that are completely unrelated as well. The “source + code” for the site (if you can call m4_abbr(HTML) @x-ref{-1} and a basic + build system source code) + @a + href="https://git.thomasvoss.com/www.thomasvoss.com" + target="_blank" + {-are available through git}. + } + + aside { + p data-ref="1" {- + The site is actually written in my own m4_abbr(GSP) language, but it + transpiles into m4_abbr(HTML). Also, this site doesn’t even have any + JavaScript. There truly is no code. + } + } + + p {- + Now go branch off to a subsection of the site: + } + + ul { + li {a href="prj" {-My Projects}} + li {a href="srp" {-Software-Related Posts}} + li {a href="www" {-Other Websites}} + li {a href="ame" {-About Me}} + } + + hr{} + + footer { m4_footer } + } + } +} diff --git a/src/index.html b/src/index.html deleted file mode 100644 index 19747dc..0000000 --- a/src/index.html +++ /dev/null @@ -1,59 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - m4_include(head.html) - </head> - <body> - <header> - <h1>Root Page</h1> - - <figure class="quote"> - <blockquote> - <p>If Java had true garbage collection, most programs would - delete themselves upon execution.</p> - </blockquote> - <figcaption> - Robert Sewell - </figcaption> - </figure> - </header> - - <main> - <p> - Welcome to my plot of the internet. This site is mostly oriented - towards topics related to software development, but you might - eventually find some things that are completely unrelated as - well. The “source code” for the site (if you can call - <abbr class="html">HTML</abbr> <x-ref>1</x-ref> and a basic build - system source code) - <a href="https://git.thomasvoss.com/www.thomasvoss.com" - target="_blank"> - are available through git</a>. - </p> - - <aside> - <p data-ref="1"> - This site doesn’t even have any JavaScript. There truly is - no code. - </p> - </aside> - - <p> - Now go branch off to a subsection of the site: - </p> - - <ul> - <li><a href="prj">My Projects</a></li> - <li><a href="srp">Software-Related Posts</a></li> - <li><a href="www">Other Websites</a></li> - <li><a href="ame">About Me</a></li> - </ul> - </main> - - <hr> - - <footer> - m4_footer - </footer> - </body> -</html> 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 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - m4_include(head.html) - </head> - <body> - <header> - <div> - <h1>My Projects</h1> - m4_include(nav.html) - </div> - - <figure class="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.</p> - </blockquote> - <figcaption> - Andy Rooney - </figcaption> - </figure> - </header> - - <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> - - <p>Posts:</p> - <ul> - <li><a href="totp">totp — generate TOTP codes</a></li> - <li><a href="mkpass">mkpass — make a password</a></li> - <li><a href="mmv">mmv, mpc — mapped file moves and -copies</a></li> - </ul> - </main> - - <hr> - - <footer> - m4_footer - </footer> - </body> -</html> 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 @@ -$ <span class="sh-fn">mkpass</span> -;%_)1S%wYO-unC6%D2pz9'bx^YFI>"VX;T[jzOUsiUr}r/R#T0Qs*XMT*fUef|2L -$ <span class="sh-fn">mkpass</span> a-zA-Z0-9 -qTneHVHfwH3b1nCanKKW24lIcsRO2TUAgp7AGbZInfsV8ZjdsR35ZikHIzyUu06x -$ <span class="sh-fn">mkpass</span> [: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 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - m4_include(head.html) - </head> - <body> - <header> - <div> - <h1>Easy Password Generation</h1> - m4_include(nav.html) - </div> - - <figure class="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.</p> - </blockquote> - <figcaption> - Sahil Malik - </figcaption> - </figure> - </header> - - <main> - <p> - <em> - You can find the <code>mkpass</code> git repository over at - <a href="https://git.sr.ht/~mango/mkpass" - target="_blank">sourcehut</a> - or <a href="https://github.com/Mango0x45/mkpass" - target="_blank">GitHub</a>. - </em> - </p> - - <h2>Table of Contents</h2> - - <ul> - <li><a href="#prologue">Prologue</a></li> - <li><a href="#usage">Basic Usage</a></li> - </ul> - - <h2 id="prologue">Prologue</h2> - <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</code> aims to be the - absolute simplest password generator possible while still providing the - functionality you need.ls - </p> - - <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™. - </p> - - <h2 id="usage">Basic Usage</h2> - <p> - The most basic usage of <code>mkpass</code> is to just - call <code>mkpass</code>. 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)</a></code> style range: - </p> - - <figure> - <pre>m4_fmt_code(basic-usage.sh.html)</pre> - </figure> - - <p> - You can also specify the length of the password using - the <code>-l</code> flag: - </p> - - <figure> - <pre>m4_fmt_code(length-flag.sh.html)</pre> - </figure> - - <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. - </p> - </main> - - <hr> - - <footer> - m4_footer - </footer> - </body> -</html> 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 @@ -$ <span class="sh-fn">mkpass</span> a-z -hxjgusvfxzfasluhlkxvsdszxbzoffkyruauiggigjmhptivctnudnkiararlwcn -$ <span class="sh-fn">mkpass</span> -l 12 a-z -wymyggnmwkwz diff --git a/src/prj/mmv/camel-to-snake-naïve.sh.gsp b/src/prj/mmv/camel-to-snake-naïve.sh.gsp new file mode 100644 index 0000000..cd0d156 --- /dev/null +++ b/src/prj/mmv/camel-to-snake-naïve.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ïve.sh.html b/src/prj/mmv/camel-to-snake-naïve.sh.html deleted file mode 100644 index 573da41..0000000 --- a/src/prj/mmv/camel-to-snake-naïve.sh.html +++ /dev/null @@ -1,2 +0,0 @@ -<span class="sh-cmt"># If you aren’t a shell-guru, take a moment to figure out how this works!</span> -$ <span class="sh-fn">ls</span> *.[ch] | <span class="sh-fn">sed</span> <span class="sh-str">'p; s/[A-Z]/\L_&/g'</span> | <span class="sh-fn">xargs</span> -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 @@ -$ <span class="sh-fn">ls</span> *.[ch] | <span class="sh-fn">mmv</span> sed <span class="sh-str">'s/[A-Z]/\L_&/g'</span> 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 @@ -$ <span class="sh-fn">git</span> ls-files <span class="sh-str">'*.[ch]'</span> | <span class="sh-fn">mmv</span> sed <span class="sh-str">'s/[A-Z]/\L_&/g'</span> 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 @@ -$ <span class="sh-fn">ls</span> | <span class="sh-fn">mmv</span> 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 @@ -$ <span class="sh-fn">ls</span> --zero | <span class="sh-fn">mmv</span> -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 @@ -$ <span class="sh-fn">find</span> . -print0 | <span class="sh-fn">mmv</span> -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 @@ -$ <span class="sh-fn">ls</span> <span class="sh-str">'The Fellowship of the Ring.mp4'</span> … <span class="sh-str">'The Two Towers.mp4'</span> | \ - <span class="sh-fn">mmv</span> awk <span class="sh-str">'{ gsub(" ", "-"); printf "%02d-%s", NR, tolower($0) }'</span> 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 @@ -$ <span class="sh-fn">ls</span> foo bar | <span class="sh-fn">mmv</span> 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 @@ -$ <span class="sh-fn">ls</span> | <span class="sh-fn">mmv</span> -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 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - m4_include(head.html) - </head> - <body> - <header> - <div> - <h1>Moving Files the Right Way</h1> - m4_include(nav.html) - </div> - - <figure class="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.</p> - </blockquote> - <figcaption> - Linux Torvalds - </figcaption> - </figure> - </header> - - <main> - <p> - <em> - You can find the <code>mmv</code> git repository over at - <a href="https://git.sr.ht/~mango/mmv" target="_blank">sourcehut</a> - or <a href="https://github.com/Mango0x45/mmv" - target="_blank">GitHub</a>. - </em> - </p> - - <p> - NOTE: As of the - <a href="https://git.sr.ht/~mango/mmv/refs/v1.2.0">v1.2.0</a> release - there is now also the <code>mcp</code> utility. It behaves the same as - the <code>mmv</code> utility but it copies files instead of moving them. - It also doesn’t support the ‘<code>-n</code>’ flag as it doesn’t need to - deal with backups. - </p> - - <h2>Table of Contents</h2> - - <ul> - <li><a href="#prologue">Prologue</a></li> - <li><a href="#moving">Advanced Moving and Pitfalls</a></li> - <li><a href="#mapping">Name Mapping with <code>mmv</code></a></li> - <li><a href="#newlines">Filenames with Embedded Newlines</a></li> - <ul> - <li><a href="#0-flag">The Simple Case</a></li> - <li><a href="#e-flag">Encoding Newlines</a></li> - </ul> - <li><a href="#i-flag">Individual Execution</a></li> - <li><a href="#safety">Safety</a></li> - <li><a href="#examples">Examples</a></li> - </ul> - - <h2 id="prologue">Prologue</h2> - <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</code> utility, and it gets the job done most of the - time. Want to rename one file? Use <code>mv</code>! Want to - move a bunch of files into a directory? Use <code>mv</code>! - How could mv ever go wrong? Well I’m glad you asked! - </p> - - <h2 id="moving">Advanced Moving and Pitfalls</h2> - <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</a> - naming convention for its files: - </p> - - <figure> - <pre>m4_fmt_code(ls-files.sh.html)</pre> - </figure> - - <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</a>, - like a normal person. Well how would you do this? You use - <code>mv</code>! This is what you might end up doing: - </p> - - <figure> - <pre>m4_fmt_code(manual-mv.sh.html)</pre> - </figure> - - <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: - </p> - - <figure> - <pre>m4_fmt_code(camel-to-snake-naïve.sh.html)</pre> - </figure> - - <aside> - <p> - The given example assumes your <code>sed</code> - implementation supports ‘<code>\L</code>’ which is a - non-standard <abbr class="gnu">GNU</abbr> extension. - </p> - </aside> - - <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. - </p> - - <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</code> - actually has an ‘<code>-L</code>’ 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)</code></a> manual). - </p> - </li> - <li> - <p> - If you try to rename the file <em>foo</em> - to <em>bar</em> but <em>bar</em> already exists, you end - up deleting a file you may not have wanted to. - </p> - </li> - <li> - <p> - In a similar vein to the previous point, you need to be - very careful about schemes like renaming the - file <em>a</em> to <em>b</em> and <em>b</em> - to <em>c</em>. You run the risk of turning <em>a</em> - into <em>c</em> and losing the file <em>b</em> entirely. - </p> - </li> - <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. - </p> - </li> - </ol> - - <h2 id="mapping">Name Mapping with <code>mmv</code></h2> - - <p> - What is <code>mmv</code>? It’s the solution to all your - problems, that’s what it is! <code>mmv</code> 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()</code> 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</code>: - </p> - - <figure> - <pre>m4_fmt_code(camel-to-snake-smart.sh.html)</pre> - </figure> - - <p>Let me break down how this works.</p> - - <p> - <code>mmv</code> 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</code> reads from the standard input will be referred - to as the <em>input files</em>. Once all the input files have - been read, the utility specified by the arguments is spawned; in - this case that would be <code>sed</code> with the argument - <code>'s/[A-Z]/\L_&/g'</code>. The input files are then piped - into <code>sed</code> the exact same way that they would have - been if we ran the above commands without <code>mmv</code>, and - the output of <code>sed</code> then forms what will be referred - to as the <em>output files</em>. Once a complete list of output - files is accumulated, each input file gets renamed to its - corresponding output file. - </p> - - <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: - </p> - - <figure> - <pre>m4_fmt_code(mmv-tr.sh.html)</pre> - </figure> - - <p> - In the above example <code>mmv</code> reads 2 lines from - standard input, those being <em>LICENSE</em> - and <em>README</em>. Those are our 2 input files now. - The <code>tr</code> utility is then spawned and the input files - are piped into it. We can simulate this in the shell: - </p> - - <figure> - <pre>m4_fmt_code(tr.sh.html)</pre> - </figure> - - <p> - As you can see above, <code>tr</code> 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</code> can go ahead - and rename the files. In this case it will rename - <em>LICENSE</em> to <em>license</em> and - <em>README</em> to <em>readme</em>. For some examples, check - the <a href="#examples">examples</a> section of this page down - below. - </p> - - <h2 id="newlines">Filenames with Embedded Newlines</h2> - - <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</strong> during - the early UNIX days to go “<em>hey, this is a bad idea!</em>”, - 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> - - <p> - So how does <code>mmv</code> deal with special characters, and - newlines in particular? Well it does so by providing the user - with the <code>-0</code> and <code>-e</code> flags: - </p> - - <dl> - <dt><code>-0</code></dt> - <dd> - <p> - Tell <code>mmv</code> to expect its input to not be - separated by newlines (‘<code>\n</code>’), but by NUL - bytes (‘<code>\0</code>’). NUL bytes are the only - characters not allowed in filenames besides forward - slashes, so they are an obvious choice for an - alternative separator. - </p> - </dd> - <dt><code>-e</code></dt> - <dd> - <p> - Encode newlines in filenames before passing them to the - provided utility. Newline characters are replaced by the - literal string ‘<code>\n</code>’ and backslashes by the - literal string ‘<code>\\</code>’. After processing, the - resulting output is decoded again. - </p> - <p> - If combined with the <code>-0</code> 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. - </p> - </dd> - </dl> - - <h3 id="0-flag">The Simple Case</h3> - - <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'</code>” - syntax as this is how my shell displays embedded newlines. - </p> - - <p> - We can start by just trying to naïvely pass these 2 files - to <code>mmv</code> and use <code>rev</code> to reverse the - names, but this doesn’t work: - </p> - - <figure> - <pre>m4_fmt_code(mmv-rev.sh.html)</pre> - </figure> - - <p> - The reason this doesn’t work is because due to the line-oriented - nature of <code>ls</code> and <code>rev</code>, we are actually - trying to rename the files <em>foo</em>, <em>bar</em>, and - <em>baz</em> to the new filenames <em>zab</em>, - <em>rab</em>, and <em>oof</em>. As can be seen in the following - diagram, the embedded newline is causing our input to be ambiguous - and <code>mmv</code> can’t reliably proceed - anymore <x-ref>1</x-ref>: - </p> - - <figure> - <object data="conflict.svg" type="image/svg+xml"></object> - </figure> - - <aside> - <p data-ref="1"> - The reason you get a cryptic “file not found” error message - is because <code>mmv</code> tries to assert that all the - input files actually exist before doing anything. Since - “foo” isn’t a real file, we error out. - </p> - </aside> - - <p> - The first thing we need to do in order to proceed is to pass - the <code>-0</code> flag to <code>mmv</code>. This will - tell <code>mmv</code> that we want to use the NUL-byte as our - input separator and not the newline. We also need <code>ls</code> - to actually provide us with the filenames delimited by NUL-bytes. - Luckily <abbr class="gnu">GNU</abbr> <code>ls</code> gives us the - <code>--zero</code> flag to do just that: - </p> - - <figure> - <pre>m4_fmt_code(mmv-rev-zero.sh.html)</pre> - </figure> - - <p> - So we’re getting places, but we aren’t quite there yet. The - issue we’re getting now is that <code>mmv</code> recieved 2 - input files from the standard input, but <code>rev</code> - produced 3 output files. Why is that? Well let’s try our hand - at a little bit of command-line debugging with <code>sed</code>: - </p> - - <figure> - <pre>m4_fmt_code(sed-debugging.sh.html)</pre> - </figure> - - <p> - If you aren’t quite sure what the above is doing, here’s a quick - summary: - </p> - - <ul> - <li> - The <code>-U</code> flag given to <code>ls</code> tells it - not to sort our output. This is purely just to keep this - example clear to the reader. - </li> - <li> - The <code>-n</code> flag given to <code>sed</code> tells it - not to print the input line automatically at the end of the - provided script. - </li> - <li> - The <code>l</code> command in <code>sed</code> prints the - current input in a “visually unambiguous form”. - </li> - </ul> - - <p> - In the <code>sed</code> output, we can see that <samp>$</samp> - represents the end of a line, and <samp>\000</samp> 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</code>: - </p> - - <figure> - <pre>m4_fmt_code(sed-debugging-rev.sh.html)</pre> - </figure> - - <p> - Well wouldn’t you know it? Since <code>rev</code> <em>also</em> - 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</em> provided us with the <code>-0</code> flag - here too, so that we can properly handle NUL-delimited input. - Combining all of this together we get a final working product: - </p> - - <figure> - <pre>m4_fmt_code(reverse-embedded-newline.sh.html)</pre> - </figure> - - <h3 id="e-flag">Encoding Newlines</h3> - - <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</code>’ and - then passing your input newline-seperated to your given command - with the <code>-e</code> flag. - </p> - - <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</code> utility - from - the <a href="https://joeyh.name/code/moreutils/">moreutils</a> - collection. The <code>vipe</code> 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</code>! We do not really want to deal with - NUL-bytes in our text-editor though, so let’s just encode our - newlines: - </p> - - <figure> - <pre>m4_fmt_code(vipe.sh.html)</pre> - </figure> - - <aside> - <p> - Notice how you still need to pass the <code>-0</code> flag - to <code>mmv</code> know that our inputfiles may have - embedded newlines. - </p> - </aside> - - <p> - When running the above code example, you will see the following - in your editor: - </p> - - <figure> - <pre>m4_fmt_code(vim.html)</pre> - </figure> - - <p> - After you exit your editor, <code>mmv</code> will decode all - occurances of ‘<code>\n</code>’ back into a newline, and all - occurances of ‘<code>\\</code>’ back into a backslash: - </p> - - <figure> - <object data="e-flag.svg" type="image/svg+xml"></object> - </figure> - - <h2 id="i-flag">Individual Execution</h2> - <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</code> flag comes - into play. With the <code>-i</code> flag we can - get <code>mmv</code> 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> - - <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</a> 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"> - SHA-1 hash</a>. - On Linux we have the <code>sha1sum</code> program which reads - input from the standard input and outputs the SHA-1 hash. This - is how we would use it with <code>mmv</code>: - </p> - - <figure> - <pre>m4_fmt_code(sha1sum-long-example.sh.html)</pre> - </figure> - - <p> - Another approach is to invoke <code>mmv</code> twice: - </p> - - <figure> - <pre>m4_fmt_code(sha1sum-short-example.sh.html)</pre> - </figure> - - <p> - If you are confused about why we need to make a call - to <code>awk</code>, it’s because the <code>sha1sum</code> - 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> - - <p> - Unlike in previous examples where one process was spawned to map - all our filenames, with the <code>-i</code> flag we are spawning - a new instance for each filename. If you struggle to visualize - this, perhaps the following diagrams help: - </p> - - <figure> - <figcaption>Invoking <code>mmv</code> without <code>-i</code></figcaption> - <object data="without-i-flag.svg" type="image/svg+xml"></object> - </figure> - - <figure> - <figcaption>Invoking <code>mmv</code> with <code>-i</code></figcaption> - <object data="with-i-flag.svg" type="image/svg+xml"></object> - </figure> - - <h2 id="safety">Safety</h2> - <p> - When compared to the standard <code>for f in *; do mv $f …; - done</code> or <code>ls | … | xargs -L2 mv</code> - constructs, <code>mmv</code> is significantly more safe to use. - These are some of the safety features that are built into the - tool: - </p> - - <ol> - <li> - If the number of input- and output files differs, execution - is aborted before making any changes. - </li> - <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</em> to <em>b</em> and <em>b</em> to <em>a</em> with - no problem). - </li> - <li> - All input files must be unique and all output files must be - unique. Otherwise execution is aborted before making any - changes. - </li> - <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</code> for - recovery. - </li> - </ol> - - <p> - Due to the way <code>mmv</code> handles #2, when things do go - wrong you may find that all of your input files have - disappeared. Don’t worry though, <code>mmv</code> takes a - backup of your code before doing anything. If you - run <code>mmv</code> with the <code>-v</code> option for verbose - output, you’ll notice it backing up your stuff in - the <code>$XDG_CACHE_DIR</code> directory: - </p> - - <figure> - <pre>m4_fmt_code(mmv-verbose.sh.html)</pre> - </figure> - - <p> - Upon successful execution - the <code>$XDG_CACHE_DIR/mmv/TIMESTAMP</code> 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</code> - 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. - </p> - - <h2 id="examples">Examples</h2> - - <aside> - <p> - All of these examples are ripped straight from - the <code>mmv(1)</code> manual page. If you - installed <code>mmv</code> through a package manager or - via <code>make install</code> then you should have the - manual installed on your system. - </p> - </aside> - - <p>Swap the files <em>foo</em> and <em>bar</em>:</p> - <figure> - <pre>m4_fmt_code(examples/swap.sh.html)</pre> - </figure> - - <p> - Rename all files in the current directory to use hyphens (‘-’) - instead of spaces: - </p> - <figure> - <pre>m4_fmt_code(examples/hyphens.sh.html)</pre> - </figure> - - <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</em> to - <em>02-the-return-of-the-king.mp4</em>): - </p> - <figure> - <pre>m4_fmt_code(examples/number.sh.html)</pre> - </figure> - - <p> - Rename files interactively in your editor while encoding newline - into the literal string ‘<code>\n</code>’, making use - of <code><a href="https://linux.die.net/man/1/vipe" - target="_blank">vipe(1)</a></code> from <em>moreutils</em>: - </p> - <figure> - <pre>m4_fmt_code(examples/vipe.sh.html)</pre> - </figure> - - <p> - Rename all C source code- and header files in a git repository - to use snake_case instead of camelCase using - the <abbr class="gnu">GNU</abbr> - <code><a href="https://www.man7.org/linux/man-pages/man1/sed.1.html" - target="_blank">sed(1)</a></code> ‘<code>\n</code>’ extension: - </p> - <figure> - <pre>m4_fmt_code(examples/camel-to-snake.sh.html)</pre> - </figure> - - <p> - Lowercase all filenames within a directory hierarchy which may - contain newline characters: - </p> - <figure> - <pre>m4_fmt_code(examples/lowercase.sh.html)</pre> - </figure> - - <p> - Map filenames which may contain newlines in the current - directory with the command ‘<code>cmd</code>’, 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): - </p> - <figure> - <pre>m4_fmt_code(examples/i-flag.sh.html)</pre> - </figure> - </main> - - <hr> - - <footer> - m4_footer - </footer> - </body> -</html> diff --git a/src/prj/mmv/ls-files.sh.html b/src/prj/mmv/ls-files.sh.gsp index d24b5af..95e6af3 100644 --- a/src/prj/mmv/ls-files.sh.html +++ b/src/prj/mmv/ls-files.sh.gsp @@ -1,2 +1,2 @@ -$ <span class="sh-fn">ls</span> +$ @span .sh-fn {-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 @@ -$ <span class="sh-fn">mv</span> bytecodeVm.c bytecode_vm.c -$ <span class="sh-fn">mv</span> fastLexer.c fast_lexer.c -$ <span class="sh-fn">mv</span> fastLexer.h fast_lexer.h -$ <span class="sh-fn">mv</span> slowParser.c slow_parser.c -$ <span class="sh-fn">mv</span> 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 @@ -$ <span class="sh-fn">ls</span> --zero foo$'\n'bar baz | <span class="sh-fn">mmv</span> -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 @@ -$ <span class="sh-fn">ls</span> foo$'\n'bar baz | <span class="sh-fn">mmv</span> 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 @@ -$ <span class="sh-fn">ls</span> LICENSE README | <span class="sh-fn">mmv</span> tr A-Z a-z diff --git a/src/prj/mmv/mmv-verbose.sh.html b/src/prj/mmv/mmv-verbose.sh.gsp index 3767416..dc4dfa0 100644 --- a/src/prj/mmv/mmv-verbose.sh.html +++ b/src/prj/mmv/mmv-verbose.sh.gsp @@ -1,4 +1,4 @@ -$ <span class="sh-fn">ls</span> foo bar | <span class="sh-fn">mmv</span> -v awk <span class="sh-str">'{ printf "%d-%s\n", NR, $0 }'</span> +$ @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’ 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 @@ -$ <span class="sh-fn">ls</span> --zero foo$'\n'bar baz | <span class="sh-fn">mmv</span> -0 rev -0 -$ <span class="sh-fn">ls</span> -'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 @@ -$ <span class="sh-fn">ls</span> -U --zero foo$'\n'bar baz | <span class="sh-fn">rev</span> | <span class="sh-fn">sed</span> -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 @@ -$ <span class="sh-fn">ls</span> -U --zero foo$'\n'bar baz | <span class="sh-fn">sed</span> -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 @@ -$ <span class="sh-fn">touch</span> foo bar -$ <span class="sh-fn">cat</span> <<<span class="sh-hd">EOF</span> >hash-filename -<span class="sh-hd">#!/bin/sh</span> - -<span class="sh-hd">sha1sum | awk '{ print \$1 }'</span> -<span class="sh-hd">EOF</span> -$ <span class="sh-fn">chmod</span> +x hash-filename -$ <span class="sh-fn">ls</span> foo bar | <span class="sh-fn">mmv</span> -i ./hash-filename -$ <span class="sh-fn">ls</span> -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 @@ -$ <span class="sh-fn">touch</span> foo bar -$ <span class="sh-fn">ls</span> | <span class="sh-fn">mmv</span> -i sha1sum -$ <span class="sh-fn">ls</span> | <span class="sh-fn">mmv</span> awk <span class="sh-str">'{ print $1 }'</span> -$ <span class="sh-fn">ls</span> -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 @@ -$ <span class="sh-fn">ls</span> LICENSE README | <span class="sh-fn">tr</span> 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 @@ -$ <span class="sh-fn">ls</span> --zero foo$'\n'bar baz | <span class="sh-fn">mmv</span> -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 @@ -$ <span class="sh-var">code</span>=<span class="sh-ex">`mkpass A-Z0-7`</span> -$ <span class="sh-fn">totp</span> $<span class="sh-var">code</span> -475867 -$ <span class="sh-fn">echo</span> $<span class="sh-var">code</span> | <span class="sh-fn">totp</span> -475867 -$ <span class="sh-fn">totp</span> -d 10 $<span class="sh-var">code</span> -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 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - m4_include(head.html) - </head> - <body> - <header> - <div> - <h1>Easy Password Generation</h1> - m4_include(nav.html) - </div> - - <figure class="quote"> - <blockquote> - <p>The C preprocessor is worse than m4, and I would kill myself - before I had to use m4.</p> - </blockquote> - <figcaption> - Arav K. - </figcaption> - </figure> - </header> - - <main> - <p> - <em> - You can find the <code>totp</code> git repository over at - <a href="https://git.sr.ht/~mango/totp" target="_blank">sourcehut</a> - or <a href="https://github.com/Mango0x45/totp" - target="_blank">GitHub</a>. - </em> - </p> - - <h2>Table of Contents</h2> - - <ul> - <li><a href="#prologue">Prologue</a></li> - <li><a href="#terms">Terminology</a></li> - <li><a href="#usage">Basic Usage</a></li> - <li><a href="#qr">Working with QR Codes</a></li> - </ul> - - <h2 id="prologue">Prologue</h2> - <p> - <abbr class="totp">TOTP</abbr> codes are pretty cool, and really easy to - do. They’re also the backbone of modern two-factor authentication. - With <code>totp</code> I hope to make - handling <abbr class="totp">TOTP</abbr> codes as easy and extensible as - possible. - </p> - - <h2 id="terms">Terminology</h2> - <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. - </p> - - <dl> - <dt>Secret</dt> - <dd> - <p> - Your <em>secret</em> is - a <a href="https://en.wikipedia.org/wiki/Base32" - target="_blank">base32</a> encoded secret key that you should under - no circumstances share with anyone else. It is from this secret key - that we can generate valid <abbr class="totp">TOTP</abbr> codes. - </p> - </dd> - - <dt>Digits</dt> - <dd> - <p> - Your <em>digits</em> is the length of the generated - <abbr class="totp">TOTP</abbr> in digits. If <em>digits</em> is 8, - then your generated key could be ‘01234567’. When dealing - with <abbr class="tfa">2FA</abbr> this is typically 6. - </p> - </dd> - - <dt>Period</dt> - <dd> - <p> - Your <em>period</em> it the duration for which the generated key is - valid in seconds. When working with <abbr class="tfa">2FA</abbr> - this is typically 30. - </p> - </dd> - </dl> - - <h2 id="usage">Basic Usage</h2> - <p> - <code>totp</code> takes secret keys as command-line arguments, but also - reads them from the standard input if none are provided. It assumes - that <em>digits</em> is 6 and <em>period</em> is 30. These defaults can - be changed with the <code>-d</code> and <code>-p</code> flags. - </p> - - <figure> - <pre>m4_fmt_code(basic-usage.sh.html)</pre> - </figure> - - <aside> - <p> - I’m using <code>mkpass</code> to generate a random secret. You can - see my post about <code>mkpass</code> <a href="/prj/mkpass">here</a>. - </p> - </aside> - - <h2 id="qr">Working with <abbr class="qr">QR</abbr> Codes</h2> - <p> - Often times when enabling <abbr class="tfa">2FA</abbr> on your account - on some website or platform, you will be shown - a <abbr class="qr">QR</abbr> code you can scan with - your <abbr class="tfa">2FA</abbr> mobile application. - These <abbr class="qr">QR</abbr> codes - contain <em>otpauth</em> <abbr class="uri">URI</abbr>s. We can extract - these from downloaded images using utilities such - as <code>zbarimg</code> and use them in <code>totp</code> using - the <code>-u</code> flag to enable ‘<abbr class="uri">URI</abbr> mode’ - </p> - - <figure> - <pre>m4_fmt_code(zbarimg.sh.html)</pre> - </figure> - - …and that’s all! There’s nothing else you need. You can use secret keys - and otpauth <abbr class="uri">URI</abbr>s, and you can configure - the <em>digits</em> and <em>period</em> of the generated codes. You can - generate multiple keys at once, and all outputs are printed to the - standard output. - </main> - - <hr> - - <footer> - m4_footer - </footer> - </body> -</html> 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 @@ -$ <span class="sh-fn">zbarimg</span> -q my-qr-code.svg <span class="sh-cmt"># Also works with jpg, png, etc.</span> -QR-Code:otpauth://totp/GitHub:Mango0x45?secret=O1AIWMONKWVRJY4H&issuer=GitHub -$ <span class="sh-fn">zbarimg</span> -q my-qr-code.svg | <span class="sh-fn">sed</span> s/QR-Code:// | <span class="sh-fn">totp</span> -u -554210 diff --git a/src/srp/fw-ec/fn-lock-1.diff.gsp b/src/srp/fw-ec/fn-lock-1.diff.gsp new file mode 100644 index 0000000..f847e41 --- /dev/null +++ b/src/srp/fw-ec/fn-lock-1.diff.gsp @@ -0,0 +1,12 @@ +@span .diff-meta {-diff --git a/board/hx20/board.h b/board/hx20/board.h} +@span .diff-meta {-index 7b4ea288a..cfc6a61a2 100644} +@span .diff-meta {---- a/board/hx20/board.h} +@span .diff-meta {-+++ b/board/hx20/board.h} +@span .diff-loc {-\@\@ -218,7 +218,6 \@\@} + #define CONFIG_CMD_LEDTEST + #define CONFIG_LED_PWM_COUNT 3 + #define CONFIG_LED_PWM_TASK_DISABLED +@span .diff-del {--#define CONFIG_CAPSLED_SUPPORT} + + #ifdef CONFIG_ACCEL_KX022 + #define CONFIG_LID_ANGLE diff --git a/src/srp/fw-ec/fn-lock-1.diff.html b/src/srp/fw-ec/fn-lock-1.diff.html deleted file mode 100644 index 9222d4b..0000000 --- a/src/srp/fw-ec/fn-lock-1.diff.html +++ /dev/null @@ -1,12 +0,0 @@ -<span class="diff-meta">diff --git a/board/hx20/board.h b/board/hx20/board.h</span> -<span class="diff-meta">index 7b4ea288a..cfc6a61a2 100644</span> -<span class="diff-meta">--- a/board/hx20/board.h</span> -<span class="diff-meta">+++ b/board/hx20/board.h</span> -<span class="diff-loc">@@ -218,7 +218,6 @@</span> - #define CONFIG_CMD_LEDTEST - #define CONFIG_LED_PWM_COUNT 3 - #define CONFIG_LED_PWM_TASK_DISABLED -<span class="diff-del">-#define CONFIG_CAPSLED_SUPPORT</span> - - #ifdef CONFIG_ACCEL_KX022 - #define CONFIG_LID_ANGLE diff --git a/src/srp/fw-ec/fn-lock-2.diff.gsp b/src/srp/fw-ec/fn-lock-2.diff.gsp new file mode 100644 index 0000000..7f9e702 --- /dev/null +++ b/src/srp/fw-ec/fn-lock-2.diff.gsp @@ -0,0 +1,36 @@ +@span .diff-meta {-diff --git a/board/hx20/keyboard_customization.c b/board/hx20/keyboard_customization.c} +@span .diff-meta {-index 2b91f2e0c..9a5050a0f 100644} +@span .diff-meta {---- a/board/hx20/keyboard_customization.c} +@span .diff-meta {-+++ b/board/hx20/keyboard_customization.c} +@span .diff-loc {-\@\@ -249,6 +249,23 \@\@ int fn_table_set(int8_t pressed, uint32_t fn_bit)} + return false; + \} + +@span .diff-ins {-+static void hx20_update_fnkey_led(void) {} +@span .diff-ins {-+ /* Turn the capslock light into a fn-lock light */} +@span .diff-ins {-+ gpio_set_level(GPIO_CAP_LED_L, (Fn_key & FN_LOCKED) ? 1 : 0);} +@span .diff-ins {-+\}} +@span .diff-ins {-+} +@span .diff-ins {-+/* Set the fn-lock light to the correct setting when the system resumes */} +@span .diff-ins {-+void hx20_fnkey_resume(void) {} +@span .diff-ins {-+ hx20_update_fnkey_led();} +@span .diff-ins {-+\}} +@span .diff-ins {-+DECLARE_HOOK(HOOK_CHIPSET_RESUME, hx20_fnkey_resume, HOOK_PRIO_DEFAULT);} +@span .diff-ins {-+} +@span .diff-ins {-+/* Disable the fn-lock light on suspend */} +@span .diff-ins {-+void hx20_fnkey_suspend(void) {} +@span .diff-ins {-+ gpio_set_level(GPIO_CAP_LED_L, 0);} +@span .diff-ins {-+\}} +@span .diff-ins {-+DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, hx20_fnkey_suspend, HOOK_PRIO_DEFAULT);} +@span .diff-ins {-+} + void fnkey_shutdown(void) { + uint8_t current_kb = 0; + +@span .diff-loc {-\@\@ -420,6 +437,7 \@\@ int functional_hotkey(uint16_t *key_code, int8_t pressed)} + Fn_key &= ~FN_LOCKED; + else + Fn_key |= FN_LOCKED; +@span .diff-ins {-+ hx20_update_fnkey_led();} + \} + return EC_ERROR_UNIMPLEMENTED; + \} diff --git a/src/srp/fw-ec/fn-lock-2.diff.html b/src/srp/fw-ec/fn-lock-2.diff.html deleted file mode 100644 index f1a7a39..0000000 --- a/src/srp/fw-ec/fn-lock-2.diff.html +++ /dev/null @@ -1,36 +0,0 @@ -<span class="diff-meta">diff --git a/board/hx20/keyboard_customization.c b/board/hx20/keyboard_customization.c</span> -<span class="diff-meta">index 2b91f2e0c..9a5050a0f 100644</span> -<span class="diff-meta">--- a/board/hx20/keyboard_customization.c</span> -<span class="diff-meta">+++ b/board/hx20/keyboard_customization.c</span> -<span class="diff-loc">@@ -249,6 +249,23 @@ int fn_table_set(int8_t pressed, uint32_t fn_bit)</span> - return false; - } - -<span class="diff-ins">+static void hx20_update_fnkey_led(void) {</span> -<span class="diff-ins">+ /* Turn the capslock light into a fn-lock light */</span> -<span class="diff-ins">+ gpio_set_level(GPIO_CAP_LED_L, (Fn_key & FN_LOCKED) ? 1 : 0);</span> -<span class="diff-ins">+}</span> -<span class="diff-ins">+</span> -<span class="diff-ins">+/* Set the fn-lock light to the correct setting when the system resumes */</span> -<span class="diff-ins">+void hx20_fnkey_resume(void) {</span> -<span class="diff-ins">+ hx20_update_fnkey_led();</span> -<span class="diff-ins">+}</span> -<span class="diff-ins">+DECLARE_HOOK(HOOK_CHIPSET_RESUME, hx20_fnkey_resume, HOOK_PRIO_DEFAULT);</span> -<span class="diff-ins">+</span> -<span class="diff-ins">+/* Disable the fn-lock light on suspend */</span> -<span class="diff-ins">+void hx20_fnkey_suspend(void) {</span> -<span class="diff-ins">+ gpio_set_level(GPIO_CAP_LED_L, 0);</span> -<span class="diff-ins">+}</span> -<span class="diff-ins">+DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, hx20_fnkey_suspend, HOOK_PRIO_DEFAULT);</span> -<span class="diff-ins">+</span> - void fnkey_shutdown(void) { - uint8_t current_kb = 0; - -<span class="diff-loc">@@ -420,6 +437,7 @@ int functional_hotkey(uint16_t *key_code, int8_t pressed)</span> - Fn_key &= ~FN_LOCKED; - else - Fn_key |= FN_LOCKED; -<span class="diff-ins">+ hx20_update_fnkey_led();</span> - } - return EC_ERROR_UNIMPLEMENTED; - } diff --git a/src/srp/fw-ec/hybrid.diff.gsp b/src/srp/fw-ec/hybrid.diff.gsp new file mode 100644 index 0000000..dfd4518 --- /dev/null +++ b/src/srp/fw-ec/hybrid.diff.gsp @@ -0,0 +1,88 @@ +@span .diff-meta {-diff --git a/board/hx20/keyboard_customization.c b/board/hx20/keyboard_customization.c} +@span .diff-meta {-index 9a5050a0f..2756f17ce 100644} +@span .diff-meta {---- a/board/hx20/keyboard_customization.c} +@span .diff-meta {-+++ b/board/hx20/keyboard_customization.c} +@span .diff-loc {-\@\@ -22,12 +22,15 \@\@} + #define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ## args) + #define CPRINTF(format, args...) cprintf(CC_KEYBOARD, format, ## args) + +@span .diff-ins {-+/* The scancode for the caps-lock key, which is now a hybrid key */} +@span .diff-ins {-+#define SCANCODE_CTRL_ESC 0x0101} +@span .diff-ins {-+} + uint16_t scancode_set2[KEYBOARD_COLS_MAX][KEYBOARD_ROWS] = { + {0x0021, 0x007B, 0x0079, 0x0072, 0x007A, 0x0071, 0x0069, 0xe04A\}, + {0xe071, 0xe070, 0x007D, 0xe01f, 0x006c, 0xe06c, 0xe07d, 0x0077\}, + {0x0015, 0x0070, 0x00ff, 0x000D, 0x000E, 0x0016, 0x0067, 0x001c\}, + {0xe011, 0x0011, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000\}, +@span .diff-del {-- {0xe05a, 0x0029, 0x0024, 0x000c, 0x0058, 0x0026, 0x0004, 0xe07a\},} +@span .diff-ins {-+ {0xe05a, 0x0029, 0x0024, 0x000c, 0x0101, 0x0026, 0x0004, 0xe07a\},} + {0x0022, 0x001a, 0x0006, 0x0005, 0x001b, 0x001e, 0x001d, 0x0076\}, + {0x002A, 0x0032, 0x0034, 0x002c, 0x002e, 0x0025, 0x002d, 0x002b\}, + {0x003a, 0x0031, 0x0033, 0x0035, 0x0036, 0x003d, 0x003c, 0x003b\}, +@span .diff-loc {-\@\@ -497,6 +500,55 \@\@ int functional_hotkey(uint16_t *key_code, int8_t pressed)} + return EC_SUCCESS; + \} + +@span .diff-ins {-+int try_ctrl_esc(uint16_t *key_code, int8_t pressed) {} +@span .diff-ins {-+ static enum {} +@span .diff-ins {-+ NONE,} +@span .diff-ins {-+ HELD,} +@span .diff-ins {-+ CTRL} +@span .diff-ins {-+ \} ctrl_esc_state;} +@span .diff-ins {-+} +@span .diff-ins {-+ if (*key_code == SCANCODE_CTRL_ESC) {} +@span .diff-ins {-+ /* If we pressed the caps key, enter the HELD state. Otherwise,} +@span .diff-ins {-+ * we are either releasing from the HELD state or the CTRL} +@span .diff-ins {-+ * state. In both cases we should reset the state to NONE, but} +@span .diff-ins {-+ * when releasing from the HELD state we want to send an ESC and} +@span .diff-ins {-+ * when releasing from the CTRL state we want to end the CTRL.} +@span .diff-ins {-+ *} +@span .diff-ins {-+ * Also important to note is that even before we know if we’re} +@span .diff-ins {-+ * going to be acting as ESC or CTRL, we need to send a press-} +@span .diff-ins {-+ * event of the CTRL key because you can chord CTRL with mouse-} +@span .diff-ins {-+ * clicks too, not just other keys.} +@span .diff-ins {-+ */} +@span .diff-ins {-+ if (pressed) {} +@span .diff-ins {-+ ctrl_esc_state = HELD;} +@span .diff-ins {-+ simulate_keyboard(SCANCODE_LEFT_CTRL, 1);} +@span .diff-ins {-+ \} else if (ctrl_esc_state == HELD) {} +@span .diff-ins {-+ ctrl_esc_state = NONE;} +@span .diff-ins {-+ simulate_keyboard(SCANCODE_LEFT_CTRL, 0);} +@span .diff-ins {-+ simulate_keyboard(SCANCODE_ESC, 1);} +@span .diff-ins {-+ simulate_keyboard(SCANCODE_ESC, 0);} +@span .diff-ins {-+ \} else if (ctrl_esc_state == CTRL) {} +@span .diff-ins {-+ ctrl_esc_state = NONE;} +@span .diff-ins {-+ simulate_keyboard(SCANCODE_LEFT_CTRL, 0);} +@span .diff-ins {-+ \}} +@span .diff-ins {-+} +@span .diff-ins {-+ return EC_ERROR_UNIMPLEMENTED;} +@span .diff-ins {-+ \}} +@span .diff-ins {-+} +@span .diff-ins {-+ /* If we get here then we are dealing with a key that isn’t the caps} +@span .diff-ins {-+ * key. In that case we need to handle all 3 states. If the state is} +@span .diff-ins {-+ * NONE then we can just exit from this function. If it’s HELD and we} +@span .diff-ins {-+ * are pressing a key, then that’s a key-chord and we need to start a} +@span .diff-ins {-+ * CTRL. Finally, if we are in the CTRL state, there is nothing to do.} +@span .diff-ins {-+ */} +@span .diff-ins {-+ if (ctrl_esc_state == HELD && pressed) {} +@span .diff-ins {-+ ctrl_esc_state = CTRL;} +@span .diff-ins {-+ simulate_keyboard(SCANCODE_LEFT_CTRL, 1);} +@span .diff-ins {-+ \}} +@span .diff-ins {-+} +@span .diff-ins {-+ return EC_SUCCESS;} +@span .diff-ins {-+\}} +@span .diff-ins {-+} + enum ec_error_list keyboard_scancode_callback(uint16_t *make_code, + int8_t pressed) + { +@span .diff-loc {-\@\@ -521,6 +573,10 \@\@ enum ec_error_list keyboard_scancode_callback(uint16_t *make_code,} + if (!pos_get_state()) + return EC_SUCCESS; + +@span .diff-ins {-+ r = try_ctrl_esc(make_code, pressed);} +@span .diff-ins {-+ if (r != EC_SUCCESS)} +@span .diff-ins {-+ return r;} +@span .diff-ins {-+} + r = hotkey_F1_F12(make_code, Fn_key, pressed); + if (r != EC_SUCCESS) + return r; diff --git a/src/srp/fw-ec/hybrid.diff.html b/src/srp/fw-ec/hybrid.diff.html deleted file mode 100644 index 0ad9717..0000000 --- a/src/srp/fw-ec/hybrid.diff.html +++ /dev/null @@ -1,88 +0,0 @@ -<span class="diff-meta">diff --git a/board/hx20/keyboard_customization.c b/board/hx20/keyboard_customization.c</span> -<span class="diff-meta">index 9a5050a0f..2756f17ce 100644</span> -<span class="diff-meta">--- a/board/hx20/keyboard_customization.c</span> -<span class="diff-meta">+++ b/board/hx20/keyboard_customization.c</span> -<span class="diff-loc">@@ -22,12 +22,15 @@</span> - #define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ## args) - #define CPRINTF(format, args...) cprintf(CC_KEYBOARD, format, ## args) - -<span class="diff-ins">+/* The scancode for the caps-lock key, which is now a hybrid key */</span> -<span class="diff-ins">+#define SCANCODE_CTRL_ESC 0x0101</span> -<span class="diff-ins">+</span> - uint16_t scancode_set2[KEYBOARD_COLS_MAX][KEYBOARD_ROWS] = { - {0x0021, 0x007B, 0x0079, 0x0072, 0x007A, 0x0071, 0x0069, 0xe04A}, - {0xe071, 0xe070, 0x007D, 0xe01f, 0x006c, 0xe06c, 0xe07d, 0x0077}, - {0x0015, 0x0070, 0x00ff, 0x000D, 0x000E, 0x0016, 0x0067, 0x001c}, - {0xe011, 0x0011, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, -<span class="diff-del">- {0xe05a, 0x0029, 0x0024, 0x000c, 0x0058, 0x0026, 0x0004, 0xe07a},</span> -<span class="diff-ins">+ {0xe05a, 0x0029, 0x0024, 0x000c, 0x0101, 0x0026, 0x0004, 0xe07a},</span> - {0x0022, 0x001a, 0x0006, 0x0005, 0x001b, 0x001e, 0x001d, 0x0076}, - {0x002A, 0x0032, 0x0034, 0x002c, 0x002e, 0x0025, 0x002d, 0x002b}, - {0x003a, 0x0031, 0x0033, 0x0035, 0x0036, 0x003d, 0x003c, 0x003b}, -<span class="diff-loc">@@ -497,6 +500,55 @@ int functional_hotkey(uint16_t *key_code, int8_t pressed)</span> - return EC_SUCCESS; - } - -<span class="diff-ins">+int try_ctrl_esc(uint16_t *key_code, int8_t pressed) {</span> -<span class="diff-ins">+ static enum {</span> -<span class="diff-ins">+ NONE,</span> -<span class="diff-ins">+ HELD,</span> -<span class="diff-ins">+ CTRL</span> -<span class="diff-ins">+ } ctrl_esc_state;</span> -<span class="diff-ins">+</span> -<span class="diff-ins">+ if (*key_code == SCANCODE_CTRL_ESC) {</span> -<span class="diff-ins">+ /* If we pressed the caps key, enter the HELD state. Otherwise,</span> -<span class="diff-ins">+ * we are either releasing from the HELD state or the CTRL</span> -<span class="diff-ins">+ * state. In both cases we should reset the state to NONE, but</span> -<span class="diff-ins">+ * when releasing from the HELD state we want to send an ESC and</span> -<span class="diff-ins">+ * when releasing from the CTRL state we want to end the CTRL.</span> -<span class="diff-ins">+ *</span> -<span class="diff-ins">+ * Also important to note is that even before we know if we’re</span> -<span class="diff-ins">+ * going to be acting as ESC or CTRL, we need to send a press-</span> -<span class="diff-ins">+ * event of the CTRL key because you can chord CTRL with mouse-</span> -<span class="diff-ins">+ * clicks too, not just other keys.</span> -<span class="diff-ins">+ */</span> -<span class="diff-ins">+ if (pressed) {</span> -<span class="diff-ins">+ ctrl_esc_state = HELD;</span> -<span class="diff-ins">+ simulate_keyboard(SCANCODE_LEFT_CTRL, 1);</span> -<span class="diff-ins">+ } else if (ctrl_esc_state == HELD) {</span> -<span class="diff-ins">+ ctrl_esc_state = NONE;</span> -<span class="diff-ins">+ simulate_keyboard(SCANCODE_LEFT_CTRL, 0);</span> -<span class="diff-ins">+ simulate_keyboard(SCANCODE_ESC, 1);</span> -<span class="diff-ins">+ simulate_keyboard(SCANCODE_ESC, 0);</span> -<span class="diff-ins">+ } else if (ctrl_esc_state == CTRL) {</span> -<span class="diff-ins">+ ctrl_esc_state = NONE;</span> -<span class="diff-ins">+ simulate_keyboard(SCANCODE_LEFT_CTRL, 0);</span> -<span class="diff-ins">+ }</span> -<span class="diff-ins">+</span> -<span class="diff-ins">+ return EC_ERROR_UNIMPLEMENTED;</span> -<span class="diff-ins">+ }</span> -<span class="diff-ins">+</span> -<span class="diff-ins">+ /* If we get here then we are dealing with a key that isn’t the caps</span> -<span class="diff-ins">+ * key. In that case we need to handle all 3 states. If the state is</span> -<span class="diff-ins">+ * NONE then we can just exit from this function. If it’s HELD and we</span> -<span class="diff-ins">+ * are pressing a key, then that’s a key-chord and we need to start a</span> -<span class="diff-ins">+ * CTRL. Finally, if we are in the CTRL state, there is nothing to do.</span> -<span class="diff-ins">+ */</span> -<span class="diff-ins">+ if (ctrl_esc_state == HELD && pressed) {</span> -<span class="diff-ins">+ ctrl_esc_state = CTRL;</span> -<span class="diff-ins">+ simulate_keyboard(SCANCODE_LEFT_CTRL, 1);</span> -<span class="diff-ins">+ }</span> -<span class="diff-ins">+</span> -<span class="diff-ins">+ return EC_SUCCESS;</span> -<span class="diff-ins">+}</span> -<span class="diff-ins">+</span> - enum ec_error_list keyboard_scancode_callback(uint16_t *make_code, - int8_t pressed) - { -<span class="diff-loc">@@ -521,6 +573,10 @@ enum ec_error_list keyboard_scancode_callback(uint16_t *make_code,</span> - if (!pos_get_state()) - return EC_SUCCESS; - -<span class="diff-ins">+ r = try_ctrl_esc(make_code, pressed);</span> -<span class="diff-ins">+ if (r != EC_SUCCESS)</span> -<span class="diff-ins">+ return r;</span> -<span class="diff-ins">+</span> - r = hotkey_F1_F12(make_code, Fn_key, pressed); - if (r != EC_SUCCESS) - return r; diff --git a/src/srp/fw-ec/index.gsp b/src/srp/fw-ec/index.gsp new file mode 100644 index 0000000..254becc --- /dev/null +++ b/src/srp/fw-ec/index.gsp @@ -0,0 +1,229 @@ +html lang="en" { + head { m4_include(head.gsp) } + body { + header { + div { + h1 {-Framework is Awesome} + m4_include(nav.gsp) + } + + figure .quote { + blockquote { + p {= + UNIX was not designed to stop its users from doing stupid things, as + that would also stop them from doing clever things. + } + } + figcaption {-Doug Gywn} + } + } + + main { + h2 {-Table of Contents} + + ul { + li {a href="#framework" {-Framework and the EC}} + li {a href="#led" {-LED Fun!}} + li {a href="#more" {-There’s More Than One LED‽}} + li {a href="#hybrid" {-The Hybrid Key}} + li {a href="#next" {-What’s Next?}} + } + + h2 #framework {-Framework and the m4_abbr(EC)} + p {- + @a href="https://frame.work" target="_blank" {-Framework} + — for those unaware — is the coolest laptop manufacturer ever. Their + whole @em{-shtick} is producing laptops that give the user the ability + to easily and effortlessly disassemble, repair, and modify their + hardware. I highly suggest checking them out if you’re interested in + computer hardware at all. The laptops even have hotswappable I/O! + } + + p {- + Anyways getting back on topic, Framework has also been giving power to + the user on the software-side of things too! A good while ago they + open-sourced the + @a + href="https://github.com/FrameworkComputer/EmbeddedController" + target="_blank" + {-code for the embedded controller} + of their laptops, which offers all sorts of possibilities for + customization of the keyboard, m4_abbr(LED) lights, and more. + } + + h2 #led {-m4_abbr(LED) Fun!} + p {- + This is an area of the m4_abbr(EC) which I have not really looked at or + touched much. I do want to play around with this a lot more in the + coming future though! So far just for shits-and-giggles, I’ve patched + the m4_abbr(EC) to make the power-button m4_abbr(LED) green instead of + the normal boring white: + } + + aside { + p {- + Just a tip: if you want to try any of these patches out, + simply copy the diffs and paste them + into @code {-git apply}. + } + } + + figure { + figcaption { + code {-~/board/hx20/led.c} + } + pre { m4_fmt_code(led.diff.gsp) } + } + + p {- + As you can see, it’s all fairly simple. I just had to change our + @code{-EC_LED_COLOR_WHITE} for @code{-EC_LED_COLOR_GREEN}. The codebase + defines a few colors, but they’re defined as m4_abbr(RGB) tuples which + is awesome, because it opens the door to custom m4_abbr(RGB) effects in + the future! + } + + h2 #more {-There’s More Than One m4_abbr(LED)‽} + p {- + That’s right! The Framework laptop I own (13″; the 16″ releases soon + though!) has 3 more m4_abbr(LED) lights. One on the left of the + chassis, one on right of the chassis, and one on the capslock key. The + capslock m4_abbr(LED) acts as an indicator of whether or not you’ve got + capslock enabled. This is useless to me though, because my custom + keyboard layout doesn’t even support capslock (see the next section) — + so I patched it to be a function-lock indicator instead! + } + + p {- + Here’s the diff — but do take care if you want to apply similar patches + to your laptop! The files I’m editing are under @code{-board/hx20} + since I’m on an 11th Gen Intel m4_abbr(CPU). If you have a different + m4_abbr(CPU), you will probably need to fuck with different code: + } + + figure { + figcaption { + code {-~/board/hx20/board.h} + } + pre { m4_fmt_code(fn-lock-1.diff.gsp) } + } + + figure { + figcaption { + code {-~/board/hx20/keyboard-customization.c} + } + pre { m4_fmt_code(fn-lock-2.diff.gsp) } + } + + p {- + As you can see, toggling the capslock m4_abbr(LED) is as simple as + invoking @code{-gpio_set_level()}. Not only that, but disabling its + functionality with the capslock key is as easy as undefining the + @code{-CONFIG_CAPSLOCK_SUPPORT} macro. Figuring out if the function key + is locked is also really easy. The @code{-Fn_key} global variable is a + bit-field containing information pertaining to the function key, and we + also conveniently already have the @code{-FN_LOCKED} constant defined + that we can bitwise-AND with @code{-Fn_key} to check the locked state! + } + + p {- + We also setup some hooks with the @code{-DECLARE_HOOK()} macro. These + just ensure that we are behaving properly on system resume and -suspend. + } + + h2 #hybrid {-The Hybrid Key} + p {- + Wouldn’t it be cool if a physical key could represent two keys at the + same time? I thought so too. Like all Emacs users, I suffer from a + distinct lack of easily-accessible modifier keys. I need escape because + I use Vim bindings; I need left-control because all the Emacs bindings + use it; I need super for my window-managers’ bindings; I need left-alt + so I can type characters that don’t come on a standard American keyboard + (such as @em{-ß}, @em{-€}, and @em{-é}), and now I have a problem. All + my modifiers are taken, but Emacs still needs a meta key to work! + } + + figure { + figcaption {- + @cite{-Workflow} by Randall Munroe + } + img alt="XKCD Comic 1172" src="1172.png" {} + } + + p {- + What will I ever do‽ Well thanks to Framework making the m4_abbr(EC) + open-source, and conveniently giving me a file called + @code{-keyboard_customization.c}, I’m going to take two keys and stick + them in one! The basic premise is this: the capslock key is arguably + the easiest modifier key to hit, and it’s currently bound to the escape + key on my system. This is inefficient though, because nobody makes + key-bindings that chord the escape-key with another key; + chords @x-ref{-1} are always done with a modifier like control, and + Emacs is no different. So my plan was to make it so that the capslock + key when used on its own mimics an escape-key, while instead mimicking + the left-control-key when used in a chord with another key. + } + + p {- + It took me a little longer this time to figure out how to implement what + I wanted since the code isn’t as clear, but it was still a surprisingly + easy feature to patch into the m4_abbr(EC)! I basically just updated + the scancode table, swapping out the capslock scancode for my own random + one that I called @code{-SCANCODE_CTRL_ESC}. I then created a new + function called @code{-try_ctrl_esc()} which is called in the on-keyup + and -down callback function. The @code{-try_ctrl_esc()} function + handles all of the logic as you can see in the following diff; it’s + basically just a state machine: + } + + aside { + p data-ref="1" {- + If you’re confused by what I mean by a “key-chord”, I am simply + referring to pressing multiple keys in conjunction, such as when you + press “@kbd{-Ctrl + C}” to copy text. + } + } + + figure { + figcaption { + code {-~/board/hx20/keyboard_customization.c} + } + pre { m4_fmt_code(hybrid.diff.gsp) } + } + + p {- + One thing that’s good to take note of is what I return from + @code{-try_ctrl_esc()}. The general pattern for handling a keyup or + -down event is to stick the following code into + @code{-keyboard_scancode_callback()}: + } + + figure { + figcaption {- + @code{-keyboard_scancode_callback()} in + @code{-~/board/hx20/keyboard_customization.c} + } + pre { m4_fmt_code(kbd-sc-cb.c.gsp) } + } + + p {- + In @code{-my_handler_function()} (or whatever you decide to name it), + you attempt to handle the event. If you don’t want to handle a + particular event and instead want to pass it on to the next handler, you + need to return @code{-EC_SUCCESS}. If you managed to successfully + handle the event though, then you need to return an error such as + @code{-EC_ERROR_UNIMPLEMENTED}. It’s pretty stupid and makes very + little sense from a naming perspective, but oh well… + } + + h2 #next {-What’s Next?} + p {- + m4_abbr(RGB) m4_abbr(LED)s maybe. + } + } + + hr{} + + footer { m4_footer } + } +} diff --git a/src/srp/fw-ec/index.html b/src/srp/fw-ec/index.html deleted file mode 100644 index 1a2d2ec..0000000 --- a/src/srp/fw-ec/index.html +++ /dev/null @@ -1,263 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - m4_include(head.html) - </head> - <body> - <header> - <div> - <h1>Framework is Awesome</h1> - m4_include(nav.html) - </div> - - <figure class="quote"> - <blockquote> - <p>UNIX was not designed to stop its users from doing stupid - things, as that would also stop them from doing clever - things.</p> - </blockquote> - <figcaption> - Doug Gywn - </figcaption> - </figure> - </header> - - <main> - <h2>Table of Contents</h2> - - <ul> - <li><a href="#framework">Framework and the EC</a></li> - <li><a href="#led">LED Fun!</a></li> - <li><a href="#more">There’s More Than One LED‽</a></li> - <li><a href="#hybrid">The Hybrid Key</a></li> - <li><a href="#next">What’s Next?</a></li> - </ul> - - <h2 id="framework">Framework and the <abbr class="ec">EC</abbr></h2> - - <p> - <a href="https://frame.work" target="_blank"> - Framework - </a> - — for those unaware — is the coolest laptop manufacturer ever. - Their whole <em>shtick</em> is producing laptops that give the - user the ability to easily and effortlessly disassemble, repair, - and modify their hardware. I highly suggest checking them out if - you’re interested in computer hardware at all. The laptops even - have hotswappable I/O! - </p> - - <p> - Anyways getting back on topic, Framework has also been giving - power to the user on the software-side of things too! A good - while ago they open-sourced the - <a href="https://github.com/FrameworkComputer/EmbeddedController"> - code for the embedded controller - </a> - of their laptops, which offers all sorts of possibilities for - customization of the keyboard, - <abbr class="led">LED</abbr> - lights, and more. - </p> - - <h2 id="led"><abbr class="led">LED</abbr> Fun!</h2> - - <p> - This is an area of the - <abbr class="ec">EC</abbr> - which I have not really looked at or touched much. I do want to - play around with this a lot more in the coming future though! So - far just for shits-and-giggles, I’ve patched the - <abbr class="ec">EC</abbr> - to make the power-button - <abbr class="ec">LED</abbr> - green instead of the normal boring white: - </p> - - <aside> - <p> - Just a tip: if you want to try any of these patches out, - simply copy the diffs and paste them - into <code>git apply</code>. - </p> - </aside> - - <figure> - <figcaption> - <code>~/board/hx20/led.c</code> - </figcaption> - <pre>m4_fmt_code(led.diff.html)</pre> - </figure> - - <p> - As you can see, it’s all fairly simple. I just had to change our - <code>EC_LED_COLOR_WHITE</code> for - <code>EC_LED_COLOR_GREEN</code>. The codebase defines a few - colors, but they’re defined as <abbr class="rgb">RGB</abbr> - tuples which is awesome, because it opens the door to - custom <abbr class="rgb">RGB</abbr> effects in the future! - </p> - - <h2 id="more">There’s More Than One <abbr class="led">LED</abbr>‽</h2> - - <p> - That’s right! The Framework laptop I own (13″; the 16″ releases - soon though!) has 3 more <abbr class="led">LED</abbr> lights. - One on the left of the chassis, one on right of the chassis, and - one on the capslock key. The capslock - <abbr class="led">LED</abbr> acts as an indicator of whether or - not you’ve got capslock enabled. This is useless to me though, - because my custom keyboard layout doesn’t even support capslock - (see the next section) — so I patched it to be a function-lock - indicator instead! - </p> - - <p> - Here’s the diff — but do take care if you want to apply similar - patches to your laptop! The files I’m editing are under - <code>board/hx20</code> since I’m on an 11th Gen Intel - <abbr class="cpu">CPU</abbr>. If you have a different - <abbr class="cpu">CPU</abbr>, you will probably need to fuck with - different code: - </p> - - <figure> - <figcaption> - <code>~/board/hx20/board.h</code> - </figcaption> - <pre>m4_fmt_code(fn-lock-1.diff.html)</pre> - </figure> - - <figure> - <figcaption> - <code>~/board/hx20/keyboard-customization.c</code> - </figcaption> - <pre>m4_fmt_code(fn-lock-2.diff.html)</pre> - </figure> - - <p> - As you can see, toggling the capslock - <abbr class="led">LED</abbr> is as simple as - invoking <code>gpio_set_level()</code>. Not only that, but - disabling its functionality with the capslock key is as easy as - undefining the <code>CONFIG_CAPSLOCK_SUPPORT</code> macro. - Figuring out if the function key is locked is also really easy. - The <code>Fn_key</code> global variable is a bit-field containing - information pertaining to the function key, and we also - conveniently already have the <code>FN_LOCKED</code> constant - defined that we can bitwise-AND with <code>Fn_key</code> to check - the locked state! - </p> - - <p> - We also setup some hooks with the <code>DECLARE_HOOK()</code> - macro. These just ensure that we are behaving properly on system - resume and -suspend. - </p> - - <h2 id="hybrid">The Hybrid Key</h2> - - <p> - Wouldn’t it be cool if a physical key could represent two keys at - the same time? I thought so too. Like all Emacs users, I suffer - from a distinct lack of easily-accessible modifier keys. I need - escape because I use Vim bindings; I need left-control because - all the Emacs bindings use it; I need super for my - window-managers’ bindings; I need left-alt so I can type - characters that don’t come on a standard American keyboard (such - as <em>ß</em>, <em>€</em>, and <em>é</em>), and now I have a - problem. All my modifiers are taken, but Emacs still needs a - meta key to work! - </p> - <figure> - <figcaption> - <cite>Workflow</cite> by Randall Munroe - </figcaption> - <img alt="XKCD Comic 1172" src="1172.png"> - </figure> - - <p> - What will I ever do‽ Well thanks to Framework making - the <abbr class="ec">EC</abbr> open-source, and conveniently - giving me a file called <code>keyboard_customization.c</code>, - I’m going to take two keys and stick them in one! The basic - premise is this: the capslock key is arguably the easiest - modifier key to hit, and it’s currently bound to the escape key - on my system. This is inefficient though, because nobody makes - key-bindings that chord the escape-key with another key; - chords <x-ref>1</x-ref> are always done with a modifier like - control, and Emacs is no different. So my plan was to make it - so that the capslock key when used on its own mimics an - escape-key, while instead mimicking the left-control-key when - used in a chord with another key. - </p> - - <p> - It took me a little longer this time to figure out how to - implement what I wanted since the code isn’t as clear, but it was - still a surprisingly easy feature to patch into the - <abbr class="ec">EC</abbr>! I basically just updated the - scancode table, swapping out the capslock scancode for my own - random one that I called <code>SCANCODE_CTRL_ESC</code>. I then - created a new function called <code>try_ctrl_esc()</code> which - is called in the on-keyup and -down callback function. The - <code>try_ctrl_esc()</code> function handles all of the logic as - you can see in the following diff; it’s basically just a state - machine: - </p> - - <aside> - <p data-ref="1"> - If you’re confused by what I mean by a “key-chord”, I am - simply referring to pressing multiple keys in conjunction, - such as when you press “<kbd>Ctrl + C</kbd>” to copy text. - </p> - </aside> - - <figure> - <figcaption><code>~/board/hx20/keyboard_customization.c</code></figcaption> - <pre>m4_fmt_code(hybrid.diff.html)</pre> - </figure> - - <p> - One thing that’s good to take note of is what I return from - <code>try_ctrl_esc()</code>. The general pattern for handling a - keyup or -down event is to stick the following code into - <code>keyboard_scancode_callback()</code>: - </p> - - <figure> - <figcaption> - <code>keyboard_scancode_callback()</code> in - <code>~/board/hx20/keyboard_customization.c</code> - </figcaption> - <pre>m4_fmt_code(kbd-sc-cb.c.html)</pre> - </figure> - - <p> - In <code>my_handler_function()</code> (or whatever you decide to - name it), you attempt to handle the event. If you don’t want to - handle a particular event and instead want to pass it on to the - next handler, you need to return <code>EC_SUCCESS</code>. If you - managed to successfully handle the event though, then you need to - return an error such as <code>EC_ERROR_UNIMPLEMENTED</code>. - It’s pretty stupid and makes very little sense from a naming - perspective, but oh well… - </p> - - <h2 id="next">What’s Next?</h2> - - <p> - <abbr class="rgb">RGB</abbr> - <abbr class="led">LED</abbr>s - maybe. - </p> - </main> - - <hr> - - <footer> - m4_footer - </footer> - </body> -</html> diff --git a/src/srp/fw-ec/kbd-sc-cb.c.gsp b/src/srp/fw-ec/kbd-sc-cb.c.gsp new file mode 100644 index 0000000..fa03466 --- /dev/null +++ b/src/srp/fw-ec/kbd-sc-cb.c.gsp @@ -0,0 +1,6 @@ +@span .c-cmt {-/* “make_code” is the scancode. “pressed” is a boolean that is true if this is a} + @span .c-cmt {-keydown event, and false if it’s a keyup. */} + +r = @span .c-fn {-my_handler_function}(make_code, pressed); +@span .c-kw {-if} (r != @span .c-pp {-EC_SUCCESS}) + @span .c-kw {-return} r; diff --git a/src/srp/fw-ec/kbd-sc-cb.c.html b/src/srp/fw-ec/kbd-sc-cb.c.html deleted file mode 100644 index 34b7f8d..0000000 --- a/src/srp/fw-ec/kbd-sc-cb.c.html +++ /dev/null @@ -1,6 +0,0 @@ -<span class="c-cmt">/* “make_code” is the scancode. “pressed” is a boolean that is true if this is a</span> -<span class="c-cmt"> keydown event, and false if it’s a keyup. */</span> - -r = <span class="c-fn">my_handler_function</span>(make_code, pressed); -<span class="c-kw">if</span> (r != <span class="c-pp">EC_SUCCESS</span>) - <span class="c-kw">return</span> r; diff --git a/src/srp/fw-ec/led.diff.gsp b/src/srp/fw-ec/led.diff.gsp new file mode 100644 index 0000000..36e2ab3 --- /dev/null +++ b/src/srp/fw-ec/led.diff.gsp @@ -0,0 +1,32 @@ +@span .diff-meta {-diff --git a/board/hx20/led.c b/board/hx20/led.c} +@span .diff-meta {-index a4dc4564e..dacf73fda 100644} +@span .diff-meta {---- a/board/hx20/led.c} +@span .diff-meta {-+++ b/board/hx20/led.c} +@span .diff-loc {-\@\@ -283,22 +283,22 \@\@ static void led_set_power(void)} + /* don't light up when at lid close */ + if (!lid_is_open()) { + set_pwr_led_color(PWM_LED2, -1); +@span .diff-del {-- enable_pwr_breath(PWM_LED2, EC_LED_COLOR_WHITE, breath_led_length, 0);} +@span .diff-ins {-+ enable_pwr_breath(PWM_LED2, EC_LED_COLOR_GREEN, breath_led_length, 0);} + return; + \} + + if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) +@span .diff-del {-- enable_pwr_breath(PWM_LED2, EC_LED_COLOR_WHITE, breath_led_length, 1);} +@span .diff-ins {-+ enable_pwr_breath(PWM_LED2, EC_LED_COLOR_GREEN, breath_led_length, 1);} + else +@span .diff-del {-- enable_pwr_breath(PWM_LED2, EC_LED_COLOR_WHITE, breath_led_length, 0);} +@span .diff-ins {-+ enable_pwr_breath(PWM_LED2, EC_LED_COLOR_GREEN, breath_led_length, 0);} + + if (chipset_in_state(CHIPSET_STATE_ON) | power_button_enable) { + if (charge_prevent_power_on(0)) + set_pwr_led_color(PWM_LED2, (power_tick % + LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? +@span .diff-del {-- EC_LED_COLOR_WHITE : -1);} +@span .diff-ins {-+ EC_LED_COLOR_GREEN : -1);} + else +@span .diff-del {-- set_pwr_led_color(PWM_LED2, EC_LED_COLOR_WHITE);} +@span .diff-ins {-+ set_pwr_led_color(PWM_LED2, EC_LED_COLOR_GREEN);} + \} else + set_pwr_led_color(PWM_LED2, -1); + \} diff --git a/src/srp/fw-ec/led.diff.html b/src/srp/fw-ec/led.diff.html deleted file mode 100644 index 9959b0d..0000000 --- a/src/srp/fw-ec/led.diff.html +++ /dev/null @@ -1,32 +0,0 @@ -<span class="diff-meta">diff --git a/board/hx20/led.c b/board/hx20/led.c</span> -<span class="diff-meta">index a4dc4564e..dacf73fda 100644</span> -<span class="diff-meta">--- a/board/hx20/led.c</span> -<span class="diff-meta">+++ b/board/hx20/led.c</span> -<span class="diff-loc">@@ -283,22 +283,22 @@ static void led_set_power(void)</span> - /* don't light up when at lid close */ - if (!lid_is_open()) { - set_pwr_led_color(PWM_LED2, -1); -<span class="diff-del">- enable_pwr_breath(PWM_LED2, EC_LED_COLOR_WHITE, breath_led_length, 0)</span>; -<span class="diff-ins">+ enable_pwr_breath(PWM_LED2, EC_LED_COLOR_GREEN, breath_led_length, 0)</span>; - return; - } - - if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) -<span class="diff-del">- enable_pwr_breath(PWM_LED2, EC_LED_COLOR_WHITE, breath_led_length, 1)</span>; -<span class="diff-ins">+ enable_pwr_breath(PWM_LED2, EC_LED_COLOR_GREEN, breath_led_length, 1)</span>; - else -<span class="diff-del">- enable_pwr_breath(PWM_LED2, EC_LED_COLOR_WHITE, breath_led_length, 0)</span>; -<span class="diff-ins">+ enable_pwr_breath(PWM_LED2, EC_LED_COLOR_GREEN, breath_led_length, 0)</span>; - - if (chipset_in_state(CHIPSET_STATE_ON) | power_button_enable) { - if (charge_prevent_power_on(0)) - set_pwr_led_color(PWM_LED2, (power_tick % - LED_TICKS_PER_CYCLE < LED_ON_TICKS) ? -<span class="diff-del">- EC_LED_COLOR_WHITE : -1);</span> -<span class="diff-ins">+ EC_LED_COLOR_GREEN : -1);</span> - else -<span class="diff-del">- set_pwr_led_color(PWM_LED2, EC_LED_COLOR_WHITE);</span> -<span class="diff-ins">+ set_pwr_led_color(PWM_LED2, EC_LED_COLOR_GREEN);</span> - } else - set_pwr_led_color(PWM_LED2, -1); - } diff --git a/src/srp/index.gsp b/src/srp/index.gsp new file mode 100644 index 0000000..8b2ddad --- /dev/null +++ b/src/srp/index.gsp @@ -0,0 +1,40 @@ +html lang="en" { + head { m4_include(head.gsp) } + body { + header { + div { + h1 {-Sortware-Related Posts} + m4_include(nav.gsp) + } + + figure .quote { + blockquote { + p {= + Object-oriented programming is an exceptionally bad idea which could + only have originated in California. + } + } + figcaption {-Edsgar W. Dijkstra} + } + } + + main { + p {- + In this section of the website I cover random software-related stuff + that isn’t related to actual projects of mine. Posts here could be + about anything from a cool program I found, to a patch I wrote, to me + complaining about bad software design. + } + + p {-Posts:} + + ul { + li {a href="fw-ec" {-Patching My Laptop’s Embedded Controller}} + } + } + + hr{} + + footer { m4_footer } + } +} diff --git a/src/srp/index.html b/src/srp/index.html deleted file mode 100644 index f66d4ae..0000000 --- a/src/srp/index.html +++ /dev/null @@ -1,47 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - m4_include(head.html) - </head> - <body> - <header> - <div> - <h1>Software-Related Posts</h1> - m4_include(nav.html) - </div> - - <figure class="quote"> - <blockquote> - <p>Object-oriented programming is an exceptionally bad idea - which could only have originated in California.</p> - </blockquote> - <figcaption> - Edsgar W. Dijkstra - </figcaption> - </figure> - </header> - - <main> - <p> - In this section of the website I cover random software-related - stuff that isn’t related to actual projects of mine. Posts here - could be about anything from a cool program I found, to a patch I - wrote, to me complaining about bad software design. - </p> - - <p> - Posts: - </p> - - <ul> - <li><a href="fw-ec">Patching My Laptop’s Embedded Controller</a></li> - </ul> - </main> - - <hr> - - <footer> - m4_footer - </footer> - </body> -</html> diff --git a/src/style.css b/src/style.css index 78e8ef2..713e4bb 100644 --- a/src/style.css +++ b/src/style.css @@ -228,12 +228,14 @@ dl { abbr.cv::before { content: 'Curriculum Vitæ'; } abbr.ec::before { content: 'Embedded Controller'; } abbr.gnu::before { content: 'GNU’s Not UNIX'; } + abbr.gsp::before { content: 'German Shorthaired Pointer'; } abbr.html::before { content: 'Hypertext Markup Language'; } abbr.it::before { content: 'Information Technology'; } abbr.led::before { content: 'Light-Emitting Diode'; } abbr.nas::before { content: 'Network Attached Storage'; } abbr.qr::before { content: 'Quick Response'; } abbr.rgb::before { content: 'Red Green Blue'; } + abbr.sha::before { content: 'Secure Hash Algorithm'; } abbr.tfa::before { content: 'Two-Factor Authentication'; } abbr.totp::before { content: 'Time-Based One-Time Password'; } abbr.uri::before { content: 'Uniform Resource Identifier'; } diff --git a/src/www/index.gsp b/src/www/index.gsp new file mode 100644 index 0000000..c46c5bc --- /dev/null +++ b/src/www/index.gsp @@ -0,0 +1,118 @@ +html lang="en" { + head { m4_include(head.gsp) } + body { + header { + div { + h1 {-Other Websites} + m4_include(nav.gsp) + } + + figure .quote { + blockquote { + p {= + The essence of m4_abbr(XML) is this: the problem it solves it not + hard, and it does not solve the problem well. + } + } + figcaption {-Phil Wadler} + } + } + + main { + p {- + On this section of the website you can find links to all sorts of other + websites I think are somewhat interesting. Some of these are my own + sites, and some of them aren’t. Feel free to explore. + } + + h3 {-My Websites} + ul { + li { + a target="_blank" href="https://archive.thomasvoss.com" {- + @cite{-archive} — Mario Kart Wii time trials archive + } + } + li { + a target="_blank" href="https://cv.thomasvoss.com" {- + @cite{-cv} — my résumé/curriculum vitæ + } + } + li { + a target="_blank" href="https://euro.thomasvoss.com" {- + @cite{-euro} — my euro coin and -banknote collection + } + } + li { + a target="_blank" href="https://git.thomasvoss.com" {- + @cite{-git} — my git server + } + } + li { + a target="_blank" href="https://paste.thomasvoss.com" {- + @cite{-paste} — my paste server + } + } + li { + a target="_blank" href="https://retime.mcbe.wtf" {- + @cite{-retime} — a webtool for retiming speedruns + } + } + } + + h3 {-Not My Websites} + ul { + li { + a target="_blank" href="https://classicshorts.com" {- + @cite{-classicshorts} — a collection of short stories + } + } + li { + a target="_blank" href="https://iannis.io" {- + @cite{-iannis.io} — blog posts on programming topics + } + } + li { + a target="_blank" href="https://redblobgames.com" {- + @cite{-redblobgames} — algorithms in the context of video games + } + } + li { + a target="_blank" href="https://tdmm.eu" {- + @cite{-tdmm} — blog posts on low-level development + } + } + li { + a target="_blank" href="https://blog.bal-e.org/" {- + @cite{-bal-e} — it’s like tdmm.eu I guess + } + } + li { + a target="_blank" href="http://textfiles.com" {- + @cite{-textfiles} — a collection of thousands of plain-text files + } + } + li { + a target="_blank" href="https://cat-v.org" {- + @cite{-cat-v} — @q{-The Internet is not for sissies.} + } + } + } + + h3 {-Assorted Links} + ul { + li { + a + target="_blank" + href="https://web.archive.org/web/20230619115633/http://lists.warhead.org.uk/pipermail/iwe/2005-July/000130.html" + { + cite {-Why Lisp Macros are Cool} + } + } + } + } + + hr{} + + footer { m4_footer } + } +} diff --git a/src/www/index.html b/src/www/index.html deleted file mode 100644 index 82ac06c..0000000 --- a/src/www/index.html +++ /dev/null @@ -1,123 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - m4_include(head.html) - </head> - <body> - <header> - <div> - <h1>Other Websites</h1> - m4_include(nav.html) - </div> - - <figure class="quote"> - <blockquote> - <p>The essence of XML is this: the problem it solves is not - hard, and it does not solve the problem well.</p> - </blockquote> - <figcaption> - Phil Wadler - </figcaption> - </figure> - </header> - - <main> - <p> - On this section of the website you can find links to all sorts of - other websites I think are somewhat interesting. Some of these - are my own sites, and some of them aren’t. Feel free to explore. - </p> - - <p>My websites:</p> - <ul> - <li> - <a target="_blank" href="https://archive.thomasvoss.com"> - <cite>archive</cite> — Mario Kart Wii time trials archive - </a> - </li> - <li> - <a target="_blank" href="https://cv.thomasvoss.com"> - <cite>cv</cite> — my résumé/curriculum vitæ - </a> - </li> - <li> - <a target="_blank" href="https://euro.thomasvoss.com"> - <cite>euro</cite> — my euro coin and -banknote collection - </a> - </li> - <li> - <a target="_blank" href="https://git.thomasvoss.com"> - <cite>git</cite> — my git server - </a> - </li> - <li> - <a target="_blank" href="https://paste.thomasvoss.com"> - <cite>paste</cite> — my paste server - </a> - </li> - <li> - <a target="_blank" href="https://retime.mcbe.wtf"> - <cite>retime</cite> — a webtool for retiming speedruns - </a> - </li> - </ul> - - <p>Not my websites:</p> - <ul> - <li> - <a target="_blank" href="https://classicshorts.com"> - <cite>classicshorts</cite> — a collection of short stories - </a> - </li> - <li> - <a target="_blank" href="https://iannis.io"> - <cite>iannis.io</cite> — blog posts on programming topics - </a> - </li> - <li> - <a target="_blank" href="https://redblobgames.com"> - <cite>redblobgames</cite> — algorithms in the context of video games - </a> - </li> - <li> - <a target="_blank" href="https://tdmm.eu"> - <cite>tdmm</cite> — blog posts on low-level development - </a> - </li> - <li> - <a target="_blank" href="https://blog.bal-e.org/"> - <cite>bal-e</cite> — it’s like tdmm.eu I guess - </a> - </li> - <li> - <a target="_blank" href="http://textfiles.com"> - <cite>textfiles</cite> — a collection of thousands of plain-text files - </a> - </li> - <li> - <a target="_blank" href="https://cat-v.org"> - <cite>cat-v</cite> — <q>The Internet is not for sissies.</q> - </a> - </li> - </ul> - - <p>Assorted Links</p> - <ul> - <li> - <a - target="_blank" - href="https://web.archive.org/web/20230619115633/http://lists.warhead.org.uk/pipermail/iwe/2005-July/000130.html" - > - <cite>Why Lisp Macros are Cool</cite> - </a> - </li> - </ul> - </main> - - <hr> - - <footer> - m4_footer - </footer> - </body> -</html> |