From d1ea7b536427b0dfd180607534cc769f51d4cf4e Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Wed, 13 Jan 2021 21:39:35 -0800 Subject: [PATCH] Add Hugo codelines post. --- content/blog/codelines/example.png | Bin 0 -> 42591 bytes content/blog/codelines/index.md | 268 +++++++++++++++++++++++++++++ 2 files changed, 268 insertions(+) create mode 100644 content/blog/codelines/example.png create mode 100644 content/blog/codelines/index.md diff --git a/content/blog/codelines/example.png b/content/blog/codelines/example.png new file mode 100644 index 0000000000000000000000000000000000000000..aed915f9175f5e54e23924c7e3bda4b12299753a GIT binary patch literal 42591 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

knT1=ehm=k2}u%`1m;0 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�M&9>W>ZX$Knv{%~v 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 literal 0 HcmV?d00001 diff --git a/content/blog/codelines/index.md b/content/blog/codelines/index.md new file mode 100644 index 0000000..799b34b --- /dev/null +++ b/content/blog/codelines/index.md @@ -0,0 +1,268 @@ +--- +title: "Pleasant Code Includes with Hugo" +date: 2021-01-13T21:31:29-08:00 +tags: ["Hugo"] +--- + +Ever since I started [the compiler series]({{< relref "00_compiler_intro.md" >}}), +I began to include more and more fragments of code into my blog. +I didn't want to be copy-pasting my code between my project +and my Markdown files, so I quickly wrote up a Hugo [shortcode](https://gohugo.io/content-management/shortcodes/) +to pull in other files in the local directory. I've since improved on this +some more, so I thought I'd share what I created with others. + +### Including Entire Files and Lines +My needs for snippets were modest at first. For the most part, +I had a single code file that I wanted to present, so it was +acceptable to plop it in the middle of my post in one piece. +The shortcode for that was quite simple: + +``` +{{ highlight (readFile (printf "code/%s" (.Get 1))) (.Get 0) "" }} +``` + +This leverages Hugo's built-in [`highlight`](https://gohugo.io/functions/highlight/) +function to provide syntax highlighting to the included snippet. Hugo +doesn't guess at the language of the code, so you have to manually provide +it. Calling this shortcode looks as follows: + +``` +{{}} +``` + +Note that this implicitly adds the `code/` prefix to all +the files I include. This is a personal convention: I want +all my code to be inside a dedicated directory. + +Of course, including entire files only takes you so far. +What if you only need to discuss a small part of your code? +Alternaitvely, what if you want to present code piece-by-piece, +in the style of literate programming? I quickly ran into the +need to do this, for which I wrote another shortcode: + +``` +{{ $s := (readFile (printf "code/%s" (.Get 1))) }} +{{ $t := split $s "\n" }} +{{ if not (eq (int (.Get 2)) 1) }} +{{ .Scratch.Set "u" (after (sub (int (.Get 2)) 1) $t) }} +{{ else }} +{{ .Scratch.Set "u" $t }} +{{ end }} +{{ $v := first (add (sub (int (.Get 3)) (int (.Get 2))) 1) (.Scratch.Get "u") }} +{{ if (.Get 4) }} +{{ .Scratch.Set "opts" (printf ",%s" (.Get 4)) }} +{{ else }} +{{ .Scratch.Set "opts" "" }} +{{ end }} +{{ highlight (delimit $v "\n") (.Get 0) (printf "linenos=table,linenostart=%d%s" (.Get 2) (.Scratch.Get "opts")) }} +``` + +This shortcode takes a language and a filename as before, but it also takes +the numbers of the first and last lines indicating the part of the code that should be included. After +splitting the contents of the file into lines, it throws away all lines before and +after the window of code that you want to include. It seems to me (from my commit history) +that Hugo's [`after`](https://gohugo.io/functions/after/) function (which should behave +similarly to Haskell's `drop`) doesn't like to be given an argument of `0`. +I had to add a special case for when this would occur, where I simply do not invoke `after` at all. +The shortcode can be used as follows: + +``` +{{}} +``` + +To support a fuller range of Hugo's functionality, I also added an optional argument that +accepts Hugo's Chroma settings. This way, I can do things like highlight certain +lines in my code snippet, which is done as follows: + +``` +{{}} +``` + +Note that the `hl_lines` field doesn't seem to work properly with `linenostart`, which means +that the highlighted lines are counted from 1 no matter what. This is why in the above snippet, +although I include lines 31 through 39, I feed lines 7, 8, and 9 to `hl_lines`. It's unusual, +but hey, it works! + +### Linking to Referenced Code +Some time after implementing my initial system for including lines of code, +I got an email from a reader who pointed out that it was hard for them to find +the exact file I was referencing, and to view the surrounding context of the +presented lines. To address this, I decided that I'd include the link +to the file in question. After all, my website and all the associated +code is on a [Git server I host](https://dev.danilafe.com/Web-Projects/blog-static), +so any local file I'm referencing should -- assuming it was properly committed -- +show up there, too. I hardcoded the URL of the `code` directory on the web interface, +and appended the relative path of each included file to it. The shortcode came out as follows: + +``` +{{ $s := (readFile (printf "code/%s" (.Get 1))) }} +{{ $t := split $s "\n" }} +{{ if not (eq (int (.Get 2)) 1) }} +{{ .Scratch.Set "u" (after (sub (int (.Get 2)) 1) $t) }} +{{ else }} +{{ .Scratch.Set "u" $t }} +{{ end }} +{{ $v := first (add (sub (int (.Get 3)) (int (.Get 2))) 1) (.Scratch.Get "u") }} +{{ if (.Get 4) }} +{{ .Scratch.Set "opts" (printf ",%s" (.Get 4)) }} +{{ else }} +{{ .Scratch.Set "opts" "" }} +{{ end }} +

+
From {{ path.Base (.Get 1) }}, + {{ if eq (.Get 2) (.Get 3) }}line {{ .Get 2 }}{{ else }} lines {{ .Get 2 }} through {{ .Get 3 }}{{ end }}
+ {{ highlight (delimit $v "\n") (.Get 0) (printf "linenos=table,linenostart=%d%s" (.Get 2) (.Scratch.Get "opts")) }} +
+``` + +This results in code blocks like the one in the image below. The image +is the result of the `codelines` call for the Idris language, presented above. + +{{< figure src="example.png" caption="An example of how the code looks." class="medium" >}} + +I got a lot of mileage out of this setup . . . until I wanted to include code from _other_ git repositories. +For instance, I wanted to talk about my [Advent of Code](https://adventofcode.com/) submissions, +without having to copy-paste the code into my blog repository! + +### Code from Submodules +My first thought when including code from other repositories was to use submodules. +This has the added advantage of "pinning" the version of the code I'm talking about, +which means that even if I push significant changes to the other repository, the code +in my blog will remain the same. This, in turn, means that all of my `codelines` +shortcodes will work as intended. + +The problem is, most Git web interfaces (my own included) don't display paths corresponding +to submodules. Thus, even if all my code is checked out and Hugo correctly +pulls the selected lines into its HTML output, the _links to the file_ remain +broken! + +There's no easy way to address this, particularly because _different submodules +can be located on different hosts_! The Git URL used for a submodule is +not known to Hugo (since, to the best of my knowledge, it can't run +shell commands), and it could reside on `dev.danilafe.com`, or `github.com`, +or elsewhere. Fortunately, it's fairly easy to tell when a file is part +of a submodule, and which submodule that is. It's sufficient to find +the longest submodule path that matches the selected file. If no +submodule path matches, then the file is part of the blog repository, +and no special action is needed. + +Of course, this means that Hugo needs to be made aware of the various +submodules in my repository. It also needs to be aware of the submodules +_inside_ those submodules, and so on: it needs to be recursive. Git +has a command to list all submodules recursively: + +```Bash +git submodule status --recursive +``` + +However, this only prints the commit, submodule path, and the upstream branch. +I don't think there's a way to list the remotes' URLs with this command; however, +we do _need_ the URLs, since that's how we create links to the Git web interfaces. + +There's another issue: how do we let Hugo know about the various submodules, +even if we can find them? Hugo can read files, but doing any serious +text processing is downright impractical. However, Hugo +itself is not able to run commands, so it needs to be able to read in +the output of another command that _can_ find submodules. + +I settled on using Hugo's `params` configuration option. This +allows users to communicate arbitrary properties to Hugo themes +and templates. In my case, I want to communicate a collection +of submodules. I didn't know about TOML's inline tables, so +I decided to represent this collection as a map of (meaningless) +submodule names to tables: + +```TOML +[params] + [params.submoduleLinks] + [params.submoduleLinks.aoc2020] + url = "https://dev.danilafe.com/Advent-of-Code/AdventOfCode-2020/src/commit/7a8503c3fe1aa7e624e4d8672aa9b56d24b4ba82" + path = "aoc-2020" +``` + +Since it was seemingly impossible to wrangle Git into outputting +all of this information using one command, I decided +to write a quick Ruby script to generate a list of submodules +as follows. I had to use `cd` in one of my calls to Git +because Git's `--git-dir` option doesn't seem to work +with submodules, treating them like a "bare" checkout. +I also chose to use an allowlist of remote URLs, +since the URL format for linking to files in a +particular repository differs from service to service. +For now, I only use my own Git server, so only `dev.danilafe.com` +is allowed; however, just by adding `elsif`s to my code, +I can add other services in the future. + +```Ruby +puts "[params]" +puts " [params.submoduleLinks]" + +def each_submodule(base_path) + `cd #{base_path} && git submodule status`.lines do |line| + hash, path = line[1..].split " " + full_path = "#{base_path}/#{path}" + url = `git config --file #{base_path}/.gitmodules --get 'submodule.#{path}.url'`.chomp.delete_suffix(".git") + safe_name = full_path.gsub(/\/|-|_\./, "") + + if url =~ /dev.danilafe.com/ + file_url = "#{url}/src/commit/#{hash}" + else + raise "Submodule URL #{url.dump} not in a known format!" + end + + yield ({ :path => full_path, :url => file_url, :name => safe_name }) + each_submodule(full_path) { |m| yield m } + end +end + +each_submodule(".") do |m| + next unless m[:path].start_with? "./code/" + puts " [params.submoduleLinks.#{m[:name].delete_prefix(".code")}]" + puts " url = #{m[:url].dump}" + puts " path = #{m[:path].delete_prefix("./code/").dump}" +end +``` + +I pipe the output of this script into a separate configuration file +called `config-gen.toml`, and then run Hugo as follows: + +``` +hugo --config config.toml,config-gen.toml +``` + +Finally, I had to modify my shortcode to find and handle the longest submodule prefix. +Here's the relevant portion, and you can +[view the entire file here](https://dev.danilafe.com/Web-Projects/blog-static/src/commit/bfeae89ab52d1696c4a56768b7f0c6682efaff82/themes/vanilla/layouts/shortcodes/codelines.html). + +``` +{{ .Scratch.Set "bestLength" -1 }} +{{ .Scratch.Set "bestUrl" (printf "https://dev.danilafe.com/Web-Projects/blog-static/src/branch/master/code/%s" (.Get 1)) }} +{{ $filePath := (.Get 1) }} +{{ $scratch := .Scratch }} +{{ range $module, $props := .Site.Params.submoduleLinks }} +{{ $path := index $props "path" }} +{{ $bestLength := $scratch.Get "bestLength" }} +{{ if and (le $bestLength (len $path)) (hasPrefix $filePath $path) }} +{{ $scratch.Set "bestLength" (len $path) }} +{{ $scratch.Set "bestUrl" (printf "%s%s" (index $props "url") (strings.TrimPrefix $path $filePath)) }} +{{ end }} +{{ end }} +``` + +And that's what I'm using at the time of writing! + +### Conclusion +My current system for code includes allows me to do the following +things: + +* Include entire files or sections of files into the page. This +saves me from having to copy and paste code manually, which +is error prone and can cause inconsistencies. +* Provide links to the files I reference on my Git interface. +This allows users to easily view the entire file that I'm talking about. +* Correctly link to files in repositories other than my blog +repository, when they are included using submodules. This means +I don't need to manually copy and update code from other projects. + +I hope some of these shortcodes and script come in handy for someone else. +Thank you for reading!