This commit is contained in:
Nox Sluijtman 2023-03-23 11:31:53 +01:00
parent 5a4b5e3603
commit 67c7c45bcd
5 changed files with 39 additions and 46 deletions

View file

@ -3,7 +3,7 @@ title: "XMonad Promtps"
date: "2023-03-08T14:20:11+01:00" date: "2023-03-08T14:20:11+01:00"
author: "$HUMANOID" author: "$HUMANOID"
tags: ["haskell", "xmonad", "linux"] tags: ["haskell", "xmonad", "linux"]
description: "There aren't a lot of instructions or explanatiosn on creating XMonad prompts, or at least not within a minute of checking my searx instance." description: "There aren't a lot of instructions or explanations on creating XMonad prompts, or at least not within a minute of checking my searx instance. This is my attempt at filling that gap."
toc: true toc: true
--- ---
# Introduction # Introduction
@ -16,7 +16,7 @@ standard XMonad Contrib modules (`XMonad.Prompt.Shell`, `XMonad.Prompt.Ssh` and
it came to my universal/external Qutebrowser bookmarks menu and it came to my universal/external Qutebrowser bookmarks menu and
`yt-dlp`-and-`pipe-viewer` wrapper. `yt-dlp`-and-`pipe-viewer` wrapper.
This tutorial of sorts with assume _some_ Haskell knowledge or not being afraid This tutorial-of-sorts will assume _some_ Haskell knowledge or not being afraid
of diving straight into how Haskell works. I'm not going into great detail on of diving straight into how Haskell works. I'm not going into great detail on
how everything works here. how everything works here.
@ -34,7 +34,7 @@ choice="$(awk '{print$1}' $bookmarks | sort | dmenu -p "Bookmark:" -l 30)"
[ -z $choice ] || qutebrowser "$choice" [ -z $choice ] || qutebrowser "$choice"
``` ```
Things get interesting at the declaration of the `choice` variable: Things get interesting at the initialisation of the `choice` variable:
1. It takes the contents of Qutebrowser's bookmarks file 1. It takes the contents of Qutebrowser's bookmarks file
2. It sorts the results of that 2. It sorts the results of that
@ -44,7 +44,7 @@ Things get interesting at the declaration of the `choice` variable:
After this, it checks whether `choice` is empty or not and in case it isn't, After this, it checks whether `choice` is empty or not and in case it isn't,
opens Qutebrowser with its contents. opens Qutebrowser with its contents.
{{< start-details summary="Here is an example of how Qutebrowser saves its bookmarks" >}} Here is an example of how Qutebrowser saves its bookmarks:
``` ```
https://www.alpinelinux.org/ index | Alpine Linux https://www.alpinelinux.org/ index | Alpine Linux
https://www.openbsd.org/ftp.html OpenBSD: Mirrors https://www.openbsd.org/ftp.html OpenBSD: Mirrors
@ -53,7 +53,6 @@ https://xxiivv.com/ Echorridoors
https://100r.co/site/home.html 100R — home https://100r.co/site/home.html 100R — home
https://solar.lowtechmagazine.com/about.html About this website | LOW←TECH MAGAZINE https://solar.lowtechmagazine.com/about.html About this website | LOW←TECH MAGAZINE
``` ```
{{< end-details >}}
## Implementation ## Implementation
@ -69,18 +68,17 @@ Seems easy enough to implement.
### Parsing the Bookmarks file ### Parsing the Bookmarks file
Lets start off by creating a function that can parse our bookmarks file. Here we Lets start off by creating a function that can parse our bookmarks file. Here we
need something to read a file -- in this case a bookmars file -- and return its need something to read a file -- in this case a bookmarks file -- and return its
contents in the form of a list. So lets create a function that takes an arbitrary contents in the form of a list of strings.
file path and reads its contents, returning them as a list of strings.
```haskell ```haskell
fileContentList :: FilePath -> IO [String] fileContentList :: FilePath -> IO [String]
``` ```
This function takes a filepath and returns `IO [String]`. This is to This function takes a filepath -- the `Filepath` datatype is an alias for
accommodate that it has to read a file. `String` -- and returns `IO [String]`.
Now for the rest of the function: Now for the body of the function:
```haskell ```haskell
fileContentList :: FilePath -> IO [String] fileContentList :: FilePath -> IO [String]
@ -90,22 +88,24 @@ fileContentList f = do
return . uniqSort . lines $ file return . uniqSort . lines $ file
``` ```
Lets go over what is happening here. Lets go over what is happening here line by line.
`fileContentList` is a function that takes an argument `f`. `fileContentList` is a function that takes an argument `f`; then it starts a
`do` block. `do` blocks are used to put multiple functions in sequence in the
scope of a single function without having them interact with eachother.
First, it retrieves the current home directory based on the `$HOME` environment Within the `do` block, it first retrieves the current home directory based on
variable and binds it to `homeDir` using the `getEnv` function from the the `$HOME` environment variable and binds it to `homeDir` using the `getEnv`
`System.Environment` module. `getEnv` returns a string with the contents of the function from the `System.Environment` module. `getEnv` returns a string with
variable given as its argument. the contents of the variable given as its argument.
Next, it retrieves the file contents from `$HOME/path/to/file` using the Next, it retrieves the file contents from `$HOME/path/to/file` using the
`readFile`. This path is created by appending `f` to the `homeDir`. `readFile`. This path is created by appending `f` to the `homeDir`.
Now for the final line. Now for the final line.
First it takes the `file` and splits it up into a list of strings based on `\n` First it takes the `file` and splits it up into a list of strings based on
using the `lines` function. newlines using the `lines` function.
```haskell ```haskell
lines $ file lines $ file
@ -115,6 +115,7 @@ Then it pipes the result from that into `uniqSort` from the `XMonad.Prompt`
module in order to -- as the name implies -- sort it and get rid of any module in order to -- as the name implies -- sort it and get rid of any
duplicate items. duplicate items.
```haskell ```haskell
uniqSort . lines $ file uniqSort . lines $ file
``` ```
@ -127,7 +128,15 @@ And the output of that is piped into `return`:
This function will allows us to parse any given text file. To parse the This function will allows us to parse any given text file. To parse the
Qutebrowser bookmarks file, call it using `.config/qutebrowser/bookmarks/url` Qutebrowser bookmarks file, call it using `.config/qutebrowser/bookmarks/url`
> _Note_: I say "pipe" because the '`.`' function behaves quite similar to
> pipes in POSIX Shell. However, the correct way of referring to what it does
> is composition; it takes two functions and passes the output of the first
> function to the second, thereby creating -- or composing a new function. As
> apposed to how pipes in POSIX Shell work, function composition chains are
> executed from right to left.
### Creating a Prompt ### Creating a Prompt
Lets see if there is anything in the Lets see if there is anything in the
[`XMonad.Prompt`](https://hackage.haskell.org/package/xmonad-contrib-0.17.1/docs/XMonad-Prompt.html) [`XMonad.Prompt`](https://hackage.haskell.org/package/xmonad-contrib-0.17.1/docs/XMonad-Prompt.html)
module that looks like it could help us in creating a prompt. module that looks like it could help us in creating a prompt.

View file

@ -1,32 +1,16 @@
{{ define "main" }} {{ define "main" }}
{{ .Content -}} {{ .Content -}}
<div class="posts"> <div class="posts">
{{ $isntDefault := not (or (eq (trim $.Site.Params.contentTypeName " ") "rambles") (eq (trim $.Site.Params.contentTypeName " ") "")) }} {{ $isntDefault := not (or (eq (trim $.Site.Params.contentTypeName " ") "rambles") (eq (trim $.Site.Params.contentTypeName " ") "")) }} {{ $contentTypeName := cond $isntDefault (string $.Site.Params.contentTypeName) "rambles" }} {{ $PageContext := . }} {{ if .IsHome }} {{ $PageContext = .Site }} {{ end }} {{ $paginator := .Paginate (where $PageContext.RegularPages "Type" $contentTypeName) }}
{{ $contentTypeName := cond $isntDefault (string $.Site.Params.contentTypeName) "rambles" }} <table class="post-entry-meta"> {{ range first 10 .Paginator.Pages }}
{{ $PageContext := . }}
{{ if .IsHome }}
{{ $PageContext = .Site }}
{{ end }}
{{ $paginator := .Paginate (where $PageContext.RegularPages "Type" $contentTypeName) }}
<table class="post-entry-meta">
{{ range first 10 .Paginator.Pages }}
<tr> <tr>
<td><a href="{{ .RelPermalink }}">{{ .Title | markdownify}}</a></td> <td><a href="{{ .RelPermalink }}">{{ .Title | markdownify}}</a></td>
<td>{{ .Params.Date.Format "2006-01-02" }}</td> <td>{{ .Params.Date.Format "2006-01-02" }}</td>
<td>{{ .Params.Author }}</td> <td>{{ .Params.Author }}</td>
<td > {{ range .Params.tags }} #<a href="{{ (urlize (printf "tags/%s/" .)) | absLangURL }}">{{ . }}</a>&nbsp; {{ end }}</td> <td>{{ range .Params.tags }} #<a href="{{ (urlize (printf "tags/%s/" .)) | absLangURL }}">{{ . }}</a>{{ end }}</td>
<!-- </tr> {{ end }}
{{ if and (.Param "readingTime") (eq (.Param "readingTime") true) }}
<td class="post-reading-time">- {{ .ReadingTime }} min read ({{ .WordCount }} words)</td>
{{ end }}
-->
</tr>
{{ end }}
</table> </table>
<p><a class="button" href="/rambles">Read more</a></p> <p><a class="button" href="/rambles">Read more</a></p>
</div> </div>
{{ partial "stickers.html" }} {{ partial "stickers.html" }}
</div>
{{ end }} {{ end }}

View file

@ -2,7 +2,7 @@
<a title="Vector graphic" href="/logoOptimised.svg"><img src="/logoOptimised.png" /></a> <a title="Vector graphic" href="/logoOptimised.svg"><img src="/logoOptimised.png" /></a>
<ul> <ul>
<li><b>Name:</b> Marty</li> <li><b>Name:</b> Marty</li>
<li title="13-6-2001 Georgian calendar"><b>Date of birth:</b> 18-con-3167</li> <li title="13-6-2001 Gregorian calendar"><b>Date of birth:</b> 18-con-3167</li>
<li><b>Gender:</b> Not really</li> <li><b>Gender:</b> Not really</li>
<li><b>Email:</b> <a href="mailto:marty.wanderer@disroot.org">marty.wanderer@disroot.org</a></li> <li><b>Email:</b> <a href="mailto:marty.wanderer@disroot.org">marty.wanderer@disroot.org</a></li>
<li><b><a href="/keys/gpg.asc">GPG key</a></b></li> <li><b><a href="/keys/gpg.asc">GPG key</a></b></li>

@ -1 +1 @@
Subproject commit e37d6351860020f42d2ffe4784f58700a44b8b28 Subproject commit 866ddf338e94e8770de213c67ab09eb106dc8f83