diff --git a/config.toml b/config.toml
new file mode 100644
index 0000000..efec321
--- /dev/null
+++ b/config.toml
@@ -0,0 +1,26 @@
+baseURL = "https://wretched.place"
+title = "wretched.place"
+theme = "etch"
+languageCode = "en-GB"
+enableInlineShortcodes = true
+pygmentsCodeFences = true
+pygmentsUseClasses = true
+
+[params]
+ dark = "auto"
+ highlight = true
+
+[menu]
+ [[menu.main]]
+ identifier = "info"
+ name = "info"
+ title = "info"
+ url = "/info/"
+ weight = 20
+
+[permalinks]
+ posts = "/:title/"
+
+[markup.goldmark.renderer]
+ # Allows HTML in Markdown
+ unsafe = true
diff --git a/content/info/index.md b/content/info/index.md
new file mode 100644
index 0000000..f094293
--- /dev/null
+++ b/content/info/index.md
@@ -0,0 +1,3 @@
+This is a place to document bits and bobs I've been up to that have interested me.
+Expect linux and self-hosting tinkering, some novice programming, and maybe the occasional recipe.
+I tend to be a fool so take anything written here with a pinch of salt :)
diff --git a/content/posts/chess.com-api-and-the-continuing-search-for-en-passant-checkmate.md b/content/posts/chess.com-api-and-the-continuing-search-for-en-passant-checkmate.md
new file mode 100644
index 0000000..ae9bf3d
--- /dev/null
+++ b/content/posts/chess.com-api-and-the-continuing-search-for-en-passant-checkmate.md
@@ -0,0 +1,64 @@
+---
+title: chess.com api and the continuing search for en passant checkmate
+date: 2022-11-08
+tags:
+ - chess
+ - python
+draft: false
+---
+
+Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:
+
+- Parse this info for the pgn (portable game notation) of each game.
+- Write these to a file so we dont have to spend forever downloading them everytime we run the script.
+- Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.
+
+First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I'm honest I'm not sure why I was getting this error. Maybe, chess.com doesn't store pgn for all games? I don't know.
+
+```python
+def get_pgns(games):
+ pgns = []
+ for game in games:
+ try:
+ pgn = game['pgn']
+ pgns.append(pgn)
+ except KeyError:
+ print('key error um')
+ return pgns
+```
+Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.
+```python
+def write_pgns(pgns):
+ with open(month.replace('/','_')+'.csv', 'w') as f:
+ for pgn in pgns:
+ f.write(pgn)
+```
+Now a pgn looks something like this if it's just printed as a string:
+
+
+
+It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:
+```python
+moves = [ 'e4', 'e5', 'Bc4', 'Nc6', 'Qh5', 'Nf6', 'Qxf7#']
+```
+We don't need the headers, we don't need the result, and we don't really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.
+```python
+def get_move_list(pgn):
+ x = pgn.split()
+ moves = []
+ for item in x:
+ # start fresh list at move 1 - effectively skipping the headers from the list
+ if item == '1.':
+ moves = []
+ moves.append(item)
+ # gets rid of clock bits and bobs
+ elif item[0] == '{' or item[-1] == '}':
+ pass
+ else:
+ moves.append(item)
+ #remove even indexes from list
+ #this gets rid of move numbers and the result of the game
+ del moves[::2]
+ return moves
+```
+I don't doubt it could be done more elegantly but it works I guess. Next time, we'll deal with working out what a list containing an en passant checkmate would look like.
diff --git a/content/posts/chess.com-api-and-the-search-for-en-passant-checkmate.md b/content/posts/chess.com-api-and-the-search-for-en-passant-checkmate.md
new file mode 100644
index 0000000..bc7b520
--- /dev/null
+++ b/content/posts/chess.com-api-and-the-search-for-en-passant-checkmate.md
@@ -0,0 +1,53 @@
+---
+title: chess.com api and the search for en passant checkmate
+date: 2022-10-26
+tags:
+ - chess
+ - python
+draft: false
+---
+
+The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.
+
+First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn't think of any obvious way to get completely random players on the site, I used the API's lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with ->
+```python
+ def get_archive_urls(titled_urls):
+ players = []
+ for url in titled_urls:
+ title_list = requests.get(url).json()
+ title_list = title_list['players']
+ players.extend(title_list)
+
+ archive_urls = []
+ for username in players:
+ games = 'https://api.chess.com/pub/player/' + username + '/games/2022/05'
+ archive_urls.append(games)
+ return archive_urls
+
+ get_archive_urls([
+ 'https://api.chess.com/pub/titled/GM',
+ 'https://api.chess.com/pub/titled/WGM'
+ ])
+```
+This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.
+
+The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example ->
+```python
+ def grab_games(archive_urls):
+ games = []
+ for url in archive_urls:
+ archive = requests.get(url).json()
+ archive_games = archive['games']
+ games.extend(archive_games)
+ return games
+```
+Feeding the first function into the second ->
+```python
+ grab_games(get_archive_urls([
+ 'https://api.chess.com/pub/titled/GM',
+ 'https://api.chess.com/pub/titled/WGM'
+ ]))
+```
+We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here's a taster of what the list looks like printed to a terminal - lots of possiblities.
+
+
diff --git a/content/posts/configuring-a-minimal-modern-wayland-de-with-home-manager.md b/content/posts/configuring-a-minimal-modern-wayland-de-with-home-manager.md
new file mode 100644
index 0000000..6644255
--- /dev/null
+++ b/content/posts/configuring-a-minimal-modern-wayland-de-with-home-manager.md
@@ -0,0 +1,15 @@
+---
+title: configuring a dynamic, modern, and minimal DIY wayland desktop environment with home-manager
+date: 2023-06-25
+tags:
+ - nixos
+ - home-manager
+draft: true
+---
+
+### components
+
+- hyprland (window manager)
+- waybar (bar)
+- wofi (application launcher)
+- mako (notification daemon)
diff --git a/content/posts/declarative-firefox-config-with-home-manager-on-nixos.md b/content/posts/declarative-firefox-config-with-home-manager-on-nixos.md
new file mode 100644
index 0000000..e09fda2
--- /dev/null
+++ b/content/posts/declarative-firefox-config-with-home-manager-on-nixos.md
@@ -0,0 +1,82 @@
+---
+title: declarative firefox config with home-manager on nixos
+date: 2022-10-02
+tags:
+ - nixos
+ - home-manager
+draft: false
+---
+
+
+As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found [this](https://github.com/misterio77/nix-starter-configs) friendly githubber's templates to be very helpful.
+
+First of all you'll need to enable firefox with `programs.firefox.enable = true;`
+
+### EXTENSIONS
+
+This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:
+
+```nix
+{pkgs, ... }:
+ let
+ addons = pkgs.nur.repos.rycee.firefox-addons;
+ in
+ {
+ programs.firefox = {
+ extensions = with addons; [
+ ublock-origin
+ bitwarden
+ darkreader
+ ];
+ };
+ }
+```
+This is the list of [all extensions](https://nur.nix-community.org/repos/rycee/) available in the repo.
+
+### BOOKMARKS
+
+Bookmarks can be added per profile. The format for it goes something like this:
+
+```nix
+profiles.james = {
+ bookmarks = [
+ {
+ name = "best website ever!";
+ url = "https://jdysmcl.xyz";
+ }
+ {
+ name = "best OS ever";
+ url = "https://nixos.org";
+ }
+ ];
+};
+```
+
+### SETTINGS
+
+Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:
+
+```nix
+profiles.james = {
+ settings = {
+ #newtab stuff
+ "browser.startup.homepage" = "https://searx.jdysmcl.xyz";
+ "browser.newtabpage.enabled" = false;
+ "browser.newtabpage.activity-stream.enabled" = false;
+
+ #some firefox features i don't really want
+ "extensions.pocket.enabled" = false;
+ "extensions.formautofill.creditCards.enabled" = false;
+ "identity.fxaccounts.enabled" = false;
+ "signon.rememberSignons" = false;
+ "browser.search.suggest.enabled" = false;
+
+ #some privacy stuff
+ "privacy.resistFingerprinting" = true;
+ "privacy.trackingprotection.enabled" = true;
+ "dom.security.https_only_mode" = true;
+ };
+};
+```
+
+Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out [this](https://nix-community.github.io/home-manager/options.html) or alternatively run a `man home-configuration.nix`. Hope this has been helpful :)
diff --git a/content/posts/docker-on-nixos.md b/content/posts/docker-on-nixos.md
new file mode 100644
index 0000000..7c244e1
--- /dev/null
+++ b/content/posts/docker-on-nixos.md
@@ -0,0 +1,74 @@
+---
+title: translating docker to nix?!
+date: 2023-02-28
+tags:
+ - docker
+ - podman
+ - nixos
+draft: false
+---
+
+In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can't be beat. I've been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I've been playing around with the nixos approach to managing docker containers.
+
+### nix -> docker compose -> docker run
+
+To illustrate how to translate a simple example from the world of docker to nix let's have a look at the config for my [searxng](https://docs.searxng.org/) instance.
+
+
+```nix
+virtualisation.oci-containers.containers."searxng" = {
+ autoStart = true;
+ image = "searxng/searxng";
+ volumes = [
+ "/srv/searx:/etc/searxng"
+ ];
+ environment = {
+ BASE_URL = "https://searx.jdysmcl.xyz/";
+ INSTANCE_NAME = "go on big boy dont be shy";
+ };
+ ports = [ "8080:8080" ];
+};
+```
+
+Here is the same thing written in a `docker-compose.yml` style format.
+
+```yaml
+services:
+ searxng:
+ image: searxng/searxng
+ volumes:
+ - /srv/searxng:/etc/searxng
+ environment:
+ - BASE_URL=https://searx.jdysmcl.xyz/;
+ - INSTANCE_NAME=go on big boy dont be shy;
+ ports:
+ - "8080:8080"
+```
+
+Also, this is what it would look like as a simple old `docker run`.
+
+```sh
+$ docker pull searxng/searxng
+$ docker run --rm \
+ -d -p 8080:8080 \
+ -v "/srv/searxng:/etc/searxng" \
+ -e "BASE_URL=http://searx.jdysmcl.xyz/" \
+ -e "INSTANCE_NAME=go on big boy dont be shy" \
+ searxng/searxng
+```
+
+### bits and bobs
+
+As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren't exposed in [oci-containers.nix](https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix). As far as I can tell, your best bet in these scenarios is `virtualisation.oci-containers.containers..extraOptions`; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.
+
+```nix
+virtualisation.oci-containers.containers."vpn".extraOptions = [
+ "--cap-add=net_admin"
+ "--device=/dev/net/tun"
+ "--network=bridge"
+];
+```
+
+With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn't really open any more doors than docker compose but it's nice to have the option when you're already invested in the nix ecosystem.
+
+One final note: nix provides the option to choose between docker and podman with `virtualisation.oci-containers.containers.backend`. This defaults to podman.
diff --git a/content/posts/elite-dough-philosophy.md b/content/posts/elite-dough-philosophy.md
new file mode 100644
index 0000000..bc77399
--- /dev/null
+++ b/content/posts/elite-dough-philosophy.md
@@ -0,0 +1,43 @@
+---
+title: elite bread dough for lazy boys
+date: 2023-01-22
+tags:
+ - cooking
+draft: false
+---
+
+### INGREDIENTI
+
+- flour (ideally bread flour but if you don't have it, it's not the end of the world)
+- water
+- salt
+- yeast (i use the little dried packet stuff)
+
+### RATIOS
+
+To start measure the weight of flour; this is what we'll work from. You can now work out how much of the other ingredients you need using these ratios:
+
+- 65% water
+- 2% salt
+- 0.5% yeast (this amount doesn't particularly matter, as long as it's in this ballpark)
+
+So if we used 1kg of flour for example, the recipe would look like this:
+
+- 1000g flour
+- 650g water
+- 20g salt
+- 5g yeast
+
+### STEPS
+
+1. Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).
+2. Put in the fridge to slowly proof for at least a day.
+3. Remove dough as required from the fridge and place in desired baking vessel (you don't have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).
+4. Proof in vessel for an additional hour or so at room temperature.
+5. Bake!
+
+### SOME HELPFUL RESOURCES
+
+- [Jim Lahey no knead bread](https://cooking.nytimes.com/recipes/11376-no-knead-bread)
+- [Kenji video](https://www.youtube.com/watch?v=uWbl3Sr2y1Y)
+- [Ragusea pizza video](https://www.youtube.com/watch?v=o4ABOKdHEUs)
diff --git a/content/posts/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script.md b/content/posts/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script.md
new file mode 100644
index 0000000..fc213ef
--- /dev/null
+++ b/content/posts/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script.md
@@ -0,0 +1,98 @@
+---
+title: get the thoughts out of your head and into a digital format with this python journal script
+date: 2022-12-01
+tags:
+ - python
+draft: false
+---
+
+
+Since getting going with emacs I've gone down the org-mode rabbit hole a little bit. In particular the very nice [org-journal](https://github.com/bastibe/org-journal) package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I'm doing something with my text editor makes it a lot more palletable.
+
+Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal's features but allow you to use whatever editor you like with markdown.
+
+### WHAT'S THE TIME?
+
+First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python's time module:
+
+```python
+def whats_the_time(format):
+ return time.strftime(format, time.localtime(time.time()))
+```
+
+This function takes a string using [python date format codes](https://www.w3schools.com/python/gloss_python_date_format_codes.asp) and spits out the corresponding time. For example, `'%A %d %B, %Y'` would give you Wednesday 12 December, 2022.
+
+### WHAT TO CALL THE FILES?
+
+My plan is to have three options for `journal_frequency`: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the `journal_frequency` that is set:
+
+```python
+def make_filename():
+ if journal_frequency == 'daily':
+ return whats_the_time('%Y%m%d')+'.md'
+
+ elif journal_frequency == 'monthly':
+ return whats_the_time('%Y%m')+'.md'
+
+ elif journal_frequency == 'yearly':
+ return whats_the_time('%Y')+'.md'
+```
+
+### DO WE NEED A NEW FILE?
+
+As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:
+
+```python
+def new_file_required():
+ if os.path.exists(os.path.join(journal_dir,make_filename())):
+ return False
+ else:
+ return True
+```
+
+MAKING FILES AND PUTTING THINGS IN THEM
+
+Now we have that admin out the way, we're on the home straight. This function creates a file and adds a little title heading at the top using the `title_string` variable. This will be called when we do need a new file:
+
+```python
+def create_file():
+ path = os.path.join(journal_dir,make_filename())
+ with open(path, 'w') as f:
+ f.write('# ' + whats_the_time(title_string))
+```
+
+This guy adds a subheading wtih the current time as default using the `entry_string` variable. If you had `journal_frequency` set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.
+
+```python
+def write_date():
+ path = os.path.join(journal_dir,make_filename())
+ with open(path, 'a') as f:
+ f.write('\n'*2+'### '+ whats_the_time(entry_string))
+```
+
+### OPENING A TEXT EDITOR
+
+Final order of business: how to open the appropriate journal file with the user's chosen editor. For this we can use the subprocess module and [Popen](https://docs.python.org/3/library/subprocess.html#popen-constructor). By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won't work with tui programs) but it could be set to anything.
+
+```python
+def open_editor():
+ cmd = [ editor, os.path.join(journal_dir, make_filename()) ]
+ process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+```
+
+Now it's just a matter of sticking all the functions together:
+
+```python
+def main():
+ if new_file_required():
+ create_file()
+ write_date()
+ open_editor()
+ else:
+ write_date()
+ open_editor()
+
+main()
+```
+
+As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I've got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script [here](https://gitlab.com/robbygozzarder/py) atm. BYEBYE xxx
diff --git a/content/posts/getting-started-with-a-barebones-neovim-plugin-in-lua.md b/content/posts/getting-started-with-a-barebones-neovim-plugin-in-lua.md
new file mode 100644
index 0000000..101d7c2
--- /dev/null
+++ b/content/posts/getting-started-with-a-barebones-neovim-plugin-in-lua.md
@@ -0,0 +1,109 @@
+---
+title: so you want to write a neovim plugin with lua
+date: 2024-04-06
+tags:
+ - lua
+ - neovim
+draft: false
+---
+I've recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There's the [official neovim docs](https://neovim.io/doc) which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.
+
+As a demostrative MVP (minimal viable plugin) jumping-off-point, I'm going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.
+
+This is what you will want your directory structure to look like.
+
+```bash
+├── lua
+│ └── note
+│ └── init.lua
+└── plugin
+ └── note.vim
+```
+
+The `plugin/note.vim` file will look like this.
+
+```vim
+command! Note lua require("note").main()
+```
+
+This creates a custom command `Note` which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the `lua/note/init.lua` file.
+With more complex plugins this section will often be split into many files but we've just got one here as it's so simple.
+
+First things first we create a plugin object.
+
+```lua
+local note = {}
+```
+
+Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.
+
+```lua
+local defaults = {
+ note_directory = "~/notes/",
+ date_format = "%Y-%m-%d %H:%M",
+ file_extension = ".md",
+}
+```
+
+Next we need the setup function.
+This takes the user's options and merges them with our default options.
+
+```lua
+function note.setup(user_options)
+ options = vim.tbl_deep_extend("force", defaults, user_options or {})
+end
+```
+
+This is the main function where the magic happens.
+
+```lua
+function note.main()
+ local dir = options.note_directory
+ local name = os.date(options.date_format)
+ local ext = options.file_extension
+ local filename = string.format("%s%s%s", dir, name, ext)
+ local command = string.format("edit %s", filename)
+ vim.api.nvim_command(command)
+end
+```
+
+Finally we return the plugin obect.
+
+```lua
+return note
+```
+
+At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using [lazy.nvim](https://github.com/folke/lazy.nvim/).
+
+```lua
+require("lazy").setup({
+ {
+ -- local
+ dir = "~/neovim-note-plugin",
+
+ -- github
+ -- "me/neovim-note-plugin",
+
+ -- alternative non github hosting
+ -- url = "https://git.example.com/me/neovim note-plugin",
+
+ config = fucntion()
+ require("note").setup({
+ file_extension = ".org",
+ })
+ end,
+
+ }
+})
+```
+
+Hope you've enjoyed.
diff --git a/content/posts/lowkey-emacs-setup.md b/content/posts/lowkey-emacs-setup.md
new file mode 100644
index 0000000..3da646f
--- /dev/null
+++ b/content/posts/lowkey-emacs-setup.md
@@ -0,0 +1,127 @@
+---
+title: lowkey emacs setup
+date: 2022-11-18
+tags:
+ - emacs
+draft: false
+---
+
+
+About a month ago I was a little bored and thought I'd give emacs a go. There's something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There's also the quite jarring default theme which wasn't vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I've landed on a simple little setup that I've been quite enjoying. Here are a few little pointers to hopefully ease you in.
+
+### AESTHETIC NICETIES
+
+First things first, assuming you're on linux emacs is configured with a file at `~/.emacs.d/init.el`. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with `M-x load-theme`; if you want the setting to persist though you can add this to you init.el:
+
+```lisp
+(load-theme 'misterioso t)
+```
+
+There are a few themes out of the box but if you're looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I've been using nix to manage my emacs packages.
+
+Anyway we've got a theme, how about a custom startup message for our initial buffer:
+
+```lisp
+(setq inhibit-startup-message t
+ inhibit-startup-echo-area-message t
+ initial-scratch-message
+ ";;oh how i adore to edit text with emacs!")
+```
+
+Maybe you dont want those big old cumbersome toolbars cluttering up your screen:
+
+```lisp
+(scroll-bar-mode -1)
+(tool-bar-mode -1)
+(menu-bar-mode -1)
+```
+
+Perhaps some line highlighting and numbering:
+
+```lisp
+;;line numbering
+(global-display-line-numbers-mode)
+(setq display-line-numbers-type 'relative)
+
+;;line higlight
+(global-hl-line-mode t)
+```
+
+Custom font?
+
+```lisp
+(setq default-frame-alist '((font . "agave Nerd Font 14")))
+```
+
+### CUSTOM KEYBINDINGS AND EVIL
+I don't know if it's just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we'll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:
+
+```lisp
+(eval-when-compile
+ (require 'use-package))
+```
+
+These are the keybindings that I currently have going; nothing too crazy just a few simple things:
+
+```lisp
+(use-package evil
+ :config
+ (evil-mode 1)
+ (evil-select-search-module 'evil-search-module 'evil-search)
+
+ ;;manage panes
+ (define-key evil-normal-state-map (kbd "M-s") 'evil-window-split)
+ (define-key evil-normal-state-map (kbd "M-v") 'evil-window-vsplit)
+
+ (define-key evil-normal-state-map (kbd "M-h") 'evil-window-left)
+ (define-key evil-normal-state-map (kbd "M-j") 'evil-window-down)
+ (define-key evil-normal-state-map (kbd "M-k") 'evil-window-up)
+ (define-key evil-normal-state-map (kbd "M-l") 'evil-window-right)
+
+ ;;get files open quick
+ (define-key evil-normal-state-map (kbd "M-f") 'find-file)
+ (define-key evil-normal-state-map (kbd "M-b") 'dired-jump)
+
+ ;;terminal
+ (define-key evil-normal-state-map (kbd "M-t") 'ansi-term)
+
+ ;;nav buffers
+ (define-key evil-normal-state-map (kbd "M-,") (kbd "C-x "))
+ (define-key evil-normal-state-map (kbd "M-.") (kbd "C-x "))
+ )
+```
+
+### SOME FRIEDNLY IDE FEATURES YOU MAY LIKE
+
+ I don't know about you but having used vscode here and there I've become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don't have thme I feel a little sad. Emacs has it covered though as long as you're happy with installing some additional stuff. Auto-completion? Try company:
+
+```lisp
+;; enable company in all buffers
+(add-hook 'after-init-hook 'global-company-mode)
+(use-package company
+ :commands company-tng-configure-default
+ :custom
+ ;; delay to start completion
+ (company-idle-delay 0)
+ ;; nb of chars before triggering completion
+ (company-minimum-prefix-length 1)
+```
+
+You want the nice little autopair brackets?
+
+```lisp
+(use-package flex-autopair
+ :config
+ (flex-autopair-mode 1))
+```
+
+Clever commenting?
+
+```lisp
+(use-package smart-comment
+ :bind ("M-c" . smart-comment))
+```
+
+Here's a little pic of the current setup :)
+
+
diff --git a/content/posts/making-nix-colors-talk-to-neovim.md b/content/posts/making-nix-colors-talk-to-neovim.md
new file mode 100644
index 0000000..955cfb0
--- /dev/null
+++ b/content/posts/making-nix-colors-talk-to-neovim.md
@@ -0,0 +1,60 @@
+---
+title: making nix-colors talk to neovim
+date: 2023-08-18
+tags:
+ - nix-colors
+ - neovim
+ - nixos
+ - home-manager
+draft: false
+---
+
+I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with [nix-colors](https://github.com/misterio77/nix-colors) so that my neovim theme would follow color changes in home-manager.
+
+Luckily, I came across [this](https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md) handy little plugin from the lovely [mini.nvim](https://github.com/echasnovski/mini.nvim) suite of plugins which lets you create your own theme with your custom colors.
+
+Beneath is a little snippet of how you could make it all happen.
+
+```nix
+{ inputs, pkgs, ... }: {
+ imports = [
+ inputs.nix-colors.homeManagerModules.default
+ ];
+ scheme = inputs.nix-colors.schemes.onedark;
+ programs.neovim = {
+ enable = true;
+ plugins = with pkgs.vimPlugins; [
+ {
+ plugin = mini-nvim;
+ config = ''
+ lua << END
+ require('mini.base16').setup({
+ palette = {
+ base00 = '#${scheme.colors.base00}',
+ base01 = '#${scheme.colors.base01}',
+ base02 = '#${scheme.colors.base02}',
+ base03 = '#${scheme.colors.base03}',
+ base04 = '#${scheme.colors.base04}',
+ base05 = '#${scheme.colors.base05}',
+ base06 = '#${scheme.colors.base06}',
+ base07 = '#${scheme.colors.base07}',
+ base08 = '#${scheme.colors.base08}',
+ base09 = '#${scheme.colors.base09}',
+ base0A = '#${scheme.colors.base0A}',
+ base0B = '#${scheme.colors.base0B}',
+ base0C = '#${scheme.colors.base0C}',
+ base0D = '#${scheme.colors.base0D}',
+ base0E = '#${scheme.colors.base0E}',
+ base0F = '#${scheme.colors.base0F}',
+ },
+ })
+ END
+ '';
+ }
+ ];
+ };
+}
+```
+
+Happy theming!
diff --git a/content/posts/multi-user-qtile-fiddling.md b/content/posts/multi-user-qtile-fiddling.md
new file mode 100644
index 0000000..a393f4e
--- /dev/null
+++ b/content/posts/multi-user-qtile-fiddling.md
@@ -0,0 +1,112 @@
+---
+title: multi user qtile fiddling
+date: 2022-12-20
+tags:
+ - qtile
+ - python
+ - nixos
+ - home-manager
+draft: false
+---
+
+
+This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using `xdg.configFile`. This is what I do with my qtile `config.py`. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.
+
+
+### THE NUB OF THE PROBLEM
+
+I basically just want the config to work out which computer it''s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:
+
+```python
+if socket.gethostname() == 'baron':
+ # some stuff i want to happen on my desktop
+elif socket.gethostname() == 'countess':
+ # some stuff i want to happen on my laptop
+```
+
+There are three main things that I like to differ between my two computers:
+
+- widgets on my bar (I don't need brightness and battery on my desktop)
+- keybindings
+- programs to autostart
+
+### WIDGETS
+
+My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn't perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven't worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn't necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).
+
+```python
+countess_widgets = [
+ # all the great widgets i want on my laptop
+]
+
+screens = [
+ Screen(
+ top = bar.Bar(
+ widgets = countess_widgets
+ ),
+ ),
+]
+```
+
+
+
+### KEYBINDINGS
+
+For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.
+
+```python
+countess_keys = [
+ Key([m], 'Up',
+ lazy.spawn('light -A 5'),
+ desc='backlight up'
+ ),
+ Key([m], 'Down',
+ lazy.spawn('light -U 5'),
+ desc='backlight down'
+ ),
+ ]
+
+keys.extend(countess_keys)
+```
+
+You could even change a specific global binding on one computer if you knew its index in the list:
+
+```python
+keys[420] = Key([m], 'd',
+ lazy.spawn('dmenu_run'),
+ desc = 'dmenu'
+ )
+```
+
+### AUTOSTART
+
+Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:
+
+```python
+@hook.subscribe.startup_once
+def autostart():
+ processes = [
+ [
+ 'feh',
+ '--bg-scale',
+ '/home/james/pics/wallpapers/beaut.jpg'
+ ],
+ [
+ 'xrandr',
+ '--output',
+ 'DisplayPort2',
+ '--primary',
+ '--mode',
+ '1920x1080',
+ '--rate',
+ '143.85'
+ ]
+ ]
+ for p in processes:
+ subprocess.Popen(p)
+```
+
+Of course, there are many ways that this could all be achievd but I think it's quite neat having it all in my one qtile config. That's about it for today. lots of love x
+
+
+
diff --git a/content/posts/nix-colors.md b/content/posts/nix-colors.md
new file mode 100644
index 0000000..049f5ee
--- /dev/null
+++ b/content/posts/nix-colors.md
@@ -0,0 +1,125 @@
+---
+title: theming nirvana
+date: 2023-03-13
+tags:
+ - nixos
+ - home-manager
+ - nix-colors
+draft: false
+---
+
+As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: 'oh this is cool I can specify which desktop environment to use in my configuration.nix'. Next thing you know you've discovered [home-manager](https://github.com/nix-community/home-manager) and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.
+
+[Nix-colors](https://sr.ht/~misterio/nix-colors/) lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!
+
+### how to make it work
+
+This will be a quick rundown of how I've got things set up; this is basically just a rehash of [this](https://sr.ht/~misterio/nix-colors/#setup).
+
+First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my `flake.nix` look something like this.
+
+```nix
+{
+ inputs = {
+ nix-colors.url = "github:misterio77/nix-colors";
+ };
+ homeConfigurations = {
+ "randy@computer" = home-manager.lib.homeManagerConfiguration {
+ extraSpecialArgs = { inherit nix-colors; };
+ };
+}
+```
+
+Then you can import the module into your home-manager config, specify a scheme ([available schemes here](https://github.com/tinted-theming/base16-schemes)), and get to theming.
+
+Here's a simple example where I make my dunst notifications follow the everforest theme.
+
+```nix
+{ pkgs, config, nix-colors, ... }: {
+
+ imports = [
+ nix-colors.homeManagerModule
+ ];
+
+ colorScheme = nix-colors.colorSchemes.everforest;
+
+ services.dunst = {
+ enable = true;
+ urgency_normal = {
+ background = "#${config.colorScheme.colors.base01}";
+ foreground = "#${config.colorScheme.colors.base05}";
+ };
+ };
+}
+```
+
+### a couple of additional tips and tricks
+
+First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.
+
+```nix
+{ config, pkgs, inputs, ... }:
+
+let
+ inherit (inputs.nix-colors.lib-contrib { inherit pkgs; }) gtkThemeFromScheme;
+in rec {
+ gtk = {
+ enable = true;
+ theme = {
+ name = "${config.colorScheme.slug}";
+ package = gtkThemeFromScheme { scheme = config.colorScheme; };
+ };
+ };
+
+ services.xsettingsd = {
+ enable = true;
+ settings = {
+ "Net/ThemeName" = "${gtk.theme.name}";
+ "Net/IconThemeName" = "${gtk.iconTheme.name}";
+ };
+ };
+}
+
+```
+
+Second tip and trick: if you're not using nix to configure everything you can still pass your colors across in the relevant format with `home.file`. I do this for qtile.
+
+```nix
+{config, pkgs, ... }:
+ let
+ c = config.colorScheme.colors;
+ in
+{
+ home.file = {
+ ".config/qtile/colors.py" = {
+ text = ''
+ scheme = {
+ 'yellow': "#${c.base0A}",
+ 'orange': "#${c.base09}",
+ 'red': "#${c.base0F}",
+ 'magenta': "#${c.base08}",
+ 'violet': "#${c.base0E}",
+ 'blue': "#${c.base0D}",
+ 'cyan': "#${c.base0C}",
+ 'green': "#${c.base0B}",
+ }
+ '';
+ };
+ };
+}
+```
+
+You can then import the colors into your `config.py` and use them as you see fit.
+
+```python
+from colors import scheme
+
+layouts = [
+ layout.MonadTall(
+ border_normal = scheme['yellow'],
+ border_focus = scheme['green'],
+ ),
+]
+```
+
+That's it for today. Thank you to the [hero](https://github.com/Misterio77) that made this.
diff --git a/content/posts/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps.md b/content/posts/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps.md
new file mode 100644
index 0000000..94653a3
--- /dev/null
+++ b/content/posts/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps.md
@@ -0,0 +1,127 @@
+---
+title: podcast setup for broke boys whose trash phone cant hack modern apps
+date: 2023-01-24
+tags:
+ - python
+draft: false
+---
+
+I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been 'podcast-player-hopping' without success for the last couple of months trying to find something which doesn't nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:
+
+- write python script to download podcasts
+- set up cron job on my server to run script every couple of hours
+- sync podcasts across my devices using the lovely [syncthing](https://syncthing.net/)
+- listen to podcasts using vlc which my phone loves
+
+For the python script I used the lovely [feedparser](https://feedparser.readthedocs.io/en/latest/introduction.html) module for easy talking to my rss feeds.
+
+### WHERE THE PODCASTS GO
+
+First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:
+
+```python
+rss_urls = [
+ 'https://anchor.fm/s/1311c8b8/podcast/rss',
+ 'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'
+]
+```
+
+I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.
+
+```python
+def create_dirs():
+ for url in rss_urls:
+ f = feedparser.parse(url)
+ feed_name = f['feed']['title']
+ current_feeds = os.listdir(pod_dir)
+
+ if feed_name not in current_feeds:
+ os.makedirs(pod_dir + feed_name)
+```
+
+### DOWNLOADING
+
+With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.
+
+```python
+def get_pods():
+ global feed_info
+ feed_info = []
+ for url in rss_urls:
+ f = feedparser.parse(url)
+ for pod in f.entries:
+ if time.time() - time.mktime(pod.published_parsed) < (86400*7):
+ feed_name = f.feed.title
+ pod_name = pod.title
+ pod_dl = pod.enclosures[0].href
+ pod_info = [
+ feed_name,
+ pod_name,
+ pod_dl
+ ]
+ feed_info.append(pod_info)
+ return feed_info
+```
+
+This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.
+
+```python
+def get_downloads():
+ downloads = []
+ pods = os.listdir(pod_dir)
+
+ for dir in pods:
+ if os.path.isdir(pod_dir + dir):
+ for file in os.listdir(pod_dir + dir):
+ downloads.append(file)
+ return downloads
+```
+
+Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.
+
+```python
+def download():
+ a = get_pods()
+ for pod in a:
+ b = get_downloads()
+ if pod[1]+'.mp3' not in b:
+ try:
+ dl = requests.get(pod[2])
+ except:
+ print('Download Error')
+
+ with open(pod_dir + pod[0] + '/' + pod[1] + '.mp3', 'wb') as file:
+ file.write(dl.content)
+```
+
+### PRUNING
+
+As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.
+
+```python
+def trim():
+ for dir in os.listdir(pod_dir):
+ if os.path.isdir(pod_dir + dir):
+ pods = os.listdir(pod_dir + dir)
+ for pod in pods:
+ st = os.stat(pod_dir + dir + '/' + pod)
+ mtime=st.st_mtime
+ if time.time() - mtime > (86400*trim_age):
+ os.remove(pod_dir + dir + '/' + pod)
+```
+
+The last thing is to call the functions:
+
+```python
+create_dirs()
+download()
+trim()
+```
+
+Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it's working quite nicely for me. Lots of love and happy listening :)
+
+
+
+
+
+
diff --git a/content/posts/rudimentary-local-scrobbling-with-bash.md b/content/posts/rudimentary-local-scrobbling-with-bash.md
new file mode 100644
index 0000000..ad0d3fc
--- /dev/null
+++ b/content/posts/rudimentary-local-scrobbling-with-bash.md
@@ -0,0 +1,58 @@
+---
+title: rudimentary local scrobbling with bash
+date: 2022-09-13
+tags:
+ - music
+ - bash
+draft: false
+---
+
+
+There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I'll be talking specifically about my setup for recording the albums I've been listening to.
+
+### LET'S GET DOWN TO BUSINESS
+
+Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I'm playing the classic album Lemonade by Beyonce it would look like this:
+
+`/home/randy/music/Beyonce/Lemonade/`
+
+To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:
+
+```bash
+printf "%s" "$selected_path" | cut -c 18- >> scrobble
+```
+
+As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.
+
+```bash
+Abdullah Ibrahim/South Africa
+Darkside/Psychic
+SOPHIE/OIL OF EVERY PEARL'S UN-INSIDES
+Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+Townes Van Zandt
+```
+
+As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:
+
+```bash
+tac scrobble | column -t -s "/" -N " ,artist,album,track"
+```
+
+Maybe you only want the last ten things you listened to:
+
+```bash
+tail -n 10 scrobble | column -t -s "/" -N " ,artist,album,song"
+```
+
+To find our most played atrists it's a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:
+
+```bash
+for album in $(awk -F/ '{ print $2 }' scrobble | sort -u)
+ do
+ echo "'$album'/"$(awk -F/ '{ print $2 }' "$scrob_file" | grep $album | wc -l)"" >> temp
+ done
+```
+
+So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.
+
+Finally, disclaimer: I am a bash amateur so I hope nothing you've seen here was too upsetting. Lots of love x
diff --git a/content/posts/running-headscale-on-nixos.md b/content/posts/running-headscale-on-nixos.md
new file mode 100644
index 0000000..6559c65
--- /dev/null
+++ b/content/posts/running-headscale-on-nixos.md
@@ -0,0 +1,9 @@
+---
+title: adventures in running headscale on nixos
+date: 2024-06-25
+tags:
+ - nixos
+draft: true
+---
+
+
diff --git a/content/posts/setting-up-a-lean-mean-hugo-blogging-theme.md b/content/posts/setting-up-a-lean-mean-hugo-blogging-theme.md
new file mode 100644
index 0000000..fff454c
--- /dev/null
+++ b/content/posts/setting-up-a-lean-mean-hugo-blogging-theme.md
@@ -0,0 +1,87 @@
+---
+title: setting up a lean mean hugo blogging theme
+date: 2022-11-10
+tags:
+ - hugo
+draft: false
+---
+
+
+When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you've just run something like `hugo new site lovely-new-website`, entered the new directory with `cd lovely-new-website` and you've got a selection of mostly empty directories looking something like this.
+```bash
+.
+├── archetypes
+│ └── default.md
+├── config.toml
+├── content
+├── data
+├── layouts
+├── public
+├── static
+└── themes
+```
+Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend [this](https://github.com/ericmurphyxyz/hugo-starter-theme) guy which I used to get up and running. You could also check out [my theme](https://gitlab.com/robbygozzarder/mcl) which I'm using on this site that is also very simple (as you can probably see from the website lol). Once you've got a theme with (I'm using mine as an example) `git clone https://gitlab.com/robbygozzarder/mcl` and placed it in the themes directory you'll need to adjust your config.toml file to point it to this theme.
+```toml
+theme="mcl"
+```
+The directory structure of your new theme will look something like this:
+```bash
+.
+└── mcl
+ ├── archetypes
+ │ └── default.md
+ ├── layouts
+ │ ├── 404.html
+ │ ├── _default
+ │ │ ├── list.html
+ │ │ └── single.html
+ │ ├── index.html
+ │ └── partials
+ │ ├── footer.html
+ │ ├── header.html
+ │ └── nav.html
+ ├── README.md
+ └── static
+ └── css
+ └── style.css
+```
+This is where most of the magic happens:
+- The default.md file in the archetypes directory dictates what template to follow when adding new post files.
+- The layouts directory is where most of the meat is:
+ - Firstly, there's the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)
+ - Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.
+ - Partials also contains index.html which (you guessed it!) is your home page.
+- Last but not least, there's static which as you can see just has the css for the site (this is all looks though - the action happens in partials).
+
+Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:
+- Content is where you put your posts - these are just markdown files which hugo converts to html for you.
+- Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl
+- Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.
+
+Now we've got the directory what's happening where admin out the way let's have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:
+```html
+{{ partial "header.html" . }}
+
+This is mainly a place for me to document various
+bits and bobs I've been doing on my computers.
+I am a noob in most things so take anything written
+here with a pinch of salt. Lots of love :)
+
+{{ .Content }}
+{{ range .Site.RegularPages | first 5 }}
+
+ {{ .Summary }}
+
+ {{ .Date.Format "06 Jan, 2006" }} |
+ {{ .WordCount }} words |
+ {{ .ReadingTime }} mins |
+
+ {{ range (.GetTerms "tags") }}
+ {{ .LinkTitle }}
+ {{ end }}
+
+{{ end }}
+
+{{ partial "footer.html" . }}
+```
+In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I'm going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs [here](https://gohugo.io/templates/introduction).
diff --git a/content/posts/simple-nixos-config-for-static-site-on-vps.md b/content/posts/simple-nixos-config-for-static-site-on-vps.md
new file mode 100644
index 0000000..ec97579
--- /dev/null
+++ b/content/posts/simple-nixos-config-for-static-site-on-vps.md
@@ -0,0 +1,85 @@
+---
+title: simple nixos config for vps static site
+date: 2023-01-29
+tags:
+ - nixos
+draft: false
+---
+
+Setting up a little static site is something I've done a few different times on a few different operating systems. It's a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let's encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.
+
+I'm going to go through a bit of the nixos config I've got for my vps.
+
+### SSH
+
+Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.
+
+```nix
+services.openssh = {
+ enable = true;
+ ports = [ 69 ];
+ settings = {
+ passwordAuthentication = false;
+ permitRootLogin = "no";
+ };
+};
+```
+
+### ADDING A USER
+
+Generally, it's nice to have a user so you're not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.
+
+```nix
+users.users = {
+ ronald = {
+ isNormalUser = true;
+ shell = pkgs.fish;
+ extraGroups = [ "wheel" "nginx" ];
+ openssh.authorizedKeys.keyFiles = [ "/path/to/public/key/file" ]
+ };
+};
+```
+
+### NGINX
+
+I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of `/var/www/example-site` at `example-site.here`. It also opens the ports for http and https in the firewall.
+
+```nix
+services.nginx = {
+ enable = true;
+ virtualHosts."example-site.here" = {
+ enableACME = true;
+ forceSSL = true;
+ root = "/var/www/example-site/";
+ };
+};
+networking.firewall.allowedTCPPorts = [ 80 443 ];
+```
+
+### HTTPS
+
+You can also make nix deal with all the let's encrypt certbot stuff. It looks like this:
+
+```nix
+security.acme = {
+ acceptTerms = true;
+ defaults.email = "ronald@email.yes";
+};
+```
+
+This will set up certificates for any sites you set the `enableAMCE` to true option for.
+
+### CRON
+
+This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn't want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.
+
+```nix
+services.cron = {
+ enable = true;
+ systemCronJobs = [
+ "@hourly root cp -r /home/ronald/example-site /var/www/"
+ ];
+};
+```
+
+This means I can just rsync the updated site from my laptop to the server and it'll be updated within the hour. Good enough for me.
diff --git a/content/posts/ssl-reverse-proxy-for-services-running-on-tailscale.md b/content/posts/ssl-reverse-proxy-for-services-running-on-tailscale.md
new file mode 100644
index 0000000..231a748
--- /dev/null
+++ b/content/posts/ssl-reverse-proxy-for-services-running-on-tailscale.md
@@ -0,0 +1,36 @@
+---
+title: nginx reverse-proxy with SSL for services running on tailscale!
+date: 2023-09-12
+tags:
+ - tailscale
+ - nixos
+draft: true
+---
+
+So you're running something on a server somewhere. For whatever reason you cant or don't want to expose ports 80 and 443 to the outside world.
+
+```nix
+services.jellyfin.enable = true;
+
+security.acme = {
+ acceptTerms = true;
+ defaults = {
+ email = "barry@email.com";
+ dnsProvider = "cloudflare";
+ credentialsFile = "/etc/credentials.env";
+ };
+};
+
+services.nginx = {
+ enable = true;
+ virtualHosts."example.com" = {
+ enableACME = true;
+ acmeRoot = null;
+ addSSL = true;
+ locations."/" = {
+ proxyPass = "http://127.0.0.1:8096";
+ proxyWebsockets = true;
+ };
+ };
+};
+```
diff --git a/content/posts/tailscale-caddy-nixos-containers.md b/content/posts/tailscale-caddy-nixos-containers.md
new file mode 100644
index 0000000..57dadbd
--- /dev/null
+++ b/content/posts/tailscale-caddy-nixos-containers.md
@@ -0,0 +1,77 @@
+---
+title: tailscale, caddy, and nixos containers - a match made in heaven
+date: 2023-05-16
+tags:
+ - nixos
+ - caddy
+ - tailscale
+ - self-hosting
+draft: false
+---
+For a little while now I've been running some services (jellyfin etc.) on an old laptop in my house. I'm not trying to sound like a podcast ad but as a networking novice, the simplicity [tailscale](https://tailscale.com/) brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you'd have a reverse proxy and set up SSL certs so your browser doesn't get stressed and you dont have to rememeber ip addresses and port numbers.
+
+When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across [this](https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380). This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.
+
+### what to do?
+
+Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One [nixos-container](https://nixos.wiki/wiki/NixOS_Containers) for each service I wanted over https. I'd be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).
+
+```nix
+ networking.nat = {
+ enable = true;
+ internalInterfaces = ["ve-+"];
+ externalInterface = "ens3";
+ };
+
+ containers.jellyfin = {
+ autoStart = true;
+ enableTun = true;
+ privateNetwork = true;
+ hostAddress = "192.168.100.10";
+ localAddress = "192.168.100.11";
+ bindMounts = {
+ "/films" = {
+ hostPath = "/mnt/films";
+ };
+ };
+
+ config = { pkgs, ... }: {
+
+ services.tailscale = {
+ enable = true;
+ # permit caddy to get certs from tailscale
+ permitCertUid = "caddy";
+ };
+
+ services.jellyfin = {
+ enable = true;
+ openFirewall = true;
+ };
+
+ services.caddy = {
+ enable = true;
+ extraConfig = ''
+
+ jellyfin.tailnet-name.ts.net {
+ reverse_proxy localhost:8096
+ }
+
+ '';
+ };
+
+
+ # open https port
+ networking.firewall.allowedTCPPorts = [ 443 ];
+
+ system.stateVersion = "23.05";
+
+ };
+ };
+}
+```
+
+This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.
+
+Once you've logged into the container `sudo nixos-container root-login jellyfin` and authenticated with tailscale `sudo tailscale up`, you should be able to access your jellyfin in your browser at `https://jellyfin.tailnet-name.ts.net`.
+
+As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to [share](https://tailscale.com/kb/1084/sharing/) a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.
diff --git a/content/posts/teeny-tiny-bash-fetch-script.md b/content/posts/teeny-tiny-bash-fetch-script.md
new file mode 100644
index 0000000..4b5c6bb
--- /dev/null
+++ b/content/posts/teeny-tiny-bash-fetch-script.md
@@ -0,0 +1,95 @@
+---
+title: teeny tiny bash fetch script
+date: 2022-12-10
+tags:
+ - bash
+draft: false
+---
+
+
+This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn't really try that hard with the portability). I didn't think much about performance; I'm personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:
+
+```bash
+declare -A fetch=(
+ [user]="$USER"
+ [host]="$(cat /etc/hostname)"
+ [uptime]="$(uptime | awk '{print $3}' | sed 's/:/h / ; s/,/m/')"
+ [kernel]="$(awk '{print $3}' /proc/version)"
+ [distro]="$(sed -n 's/^PRETTY_NAME="//p' /etc/os-release | sed 's/"//')"
+ [shell]="$(basename $SHELL)"
+ [de]="$XDG_CURRENT_DESKTOP"
+ [terminal]="$TERM"
+ [editor]="$EDITOR"
+ [root]="$(df -Th / | tail -n 1 | awk '{print $6}'),
+ $(df -Th / | tail -n 1 | awk '{print $2}')"
+ [ip]="$(host myip.opendns.com resolver1.opendns.com |
+ tail -n 1 | awk '{print $4}')"
+ [battery]="$(cat /sys/class/power_supply/BAT0/capacity)%"
+ [cpu]="$(sed -n 5p /proc/cpuinfo | cut -d: -f2)"
+ [ram]="$(free -h | sed -n 2p | awk '{print $3}') /
+ $(free -h | sed -n 2p | awk '{print $2}')"
+ [swap]="$(free -h | sed -n 3p | awk '{print $3}') /
+ $(free -h | sed -n 3p | awk '{print $2}')"
+ [display]="$(xrandr | grep '*' | awk '{print $1}'),
+ $(xrandr | grep '*' | awk '{print $2}' | sed 's/*/Hz/ ; s/+//')"
+)
+```
+
+Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).
+
+Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:
+
+```bash
+declare -a colors=(
+ "\e[0;1;30m" # black
+ "\e[0;1;31m" # red
+ "\e[0;1;32m" # green
+ "\e[0;1;33m" # blue
+ "\e[0;1;34m" # yellow
+ "\e[0;1;35m" # pink
+ "\e[0;1;36m" # magenta
+ "\e[0;1;37m" # white
+)
+```
+
+I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable 'pre' here is the text that I want formatted:
+
+```bash
+pre="->"
+
+random_color () {
+ size=${#colors[@]}
+ index=$(($RANDOM % $size))
+ echo "${colors[$index]}${pre}\e[0m"
+}
+```
+
+My plan was then to simply loop through the array, 'echo-ing' out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative 'fetch' array:
+
+```bash
+declare -a order=(
+ "user"
+ "host"
+ "uptime" # uses uptime command
+ "kernel"
+ "distro"
+ "shell"
+ "de"
+ "terminal"
+ "editor"
+ # "ip" # uses host command
+ # "cpu"
+ # "ram" # uses free command
+ # "swap" # uses free also
+ # "root" # uses df command
+ # "battery"
+ # "display" # uses xrandr
+)
+
+for info in "${order[@]}"; do
+ echo -e "$(random_color) \e[0;1;3m$info\e[0m${sep}${fetch[$info]}"
+done
+```
+ This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety [here](https://gitlab.com/robbygozzarder/golazo). This is a pretty picture of a few variations.
+
+
diff --git a/content/posts/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal.md b/content/posts/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal.md
new file mode 100644
index 0000000..619d04d
--- /dev/null
+++ b/content/posts/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal.md
@@ -0,0 +1,71 @@
+---
+title: upgrade your qtile setup with a cute dropdown terminal
+date: 2022-09-23
+tags:
+ - python
+ - qtile
+draft: false
+---
+
+
+I didn't know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.
+
+```python
+from libqtile.config import Dropdown, Scratchpad
+
+groups = []
+```
+
+I'm then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the [qtile docs](https://docs.qtile.org/en/latest/manual/config/groups.html) is a "special - by default invisible - group which acts as a container for DropDown configurations". My configuration looks like this:
+
+```python
+groups.append(
+ ScratchPad( "scratchpad", [
+ DropDown(
+ "term",
+ kitty,
+ opacity = 0.9,
+ ),
+ ]
+ ),
+)
+```
+
+This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:
+
+
+
+Though this can easily be altered with the x, y, height, and width keys:
+
+```python
+groups.append(
+ ScratchPad("scratchpad", [
+ DropDown(
+ "term",
+ kitty,
+ opacity = 0.9,
+ x = 0,
+ y = 0,
+ width = 0.3,
+ height = 0.5,
+ ),
+ ])
+)
+```
+
+This gives us a little boxy guy in the top left corner:
+
+
+
+We also have the option to set keybindings to toggle the appearance of the window. I've got this in my config.py now:
+
+```python
+keys = [
+ Key([m, "shift"], "Return",
+ lazy.group["scratchpad"].dropdown_toggle("terminal"),
+ desc='dropdown term'
+ ),
+]
+```
+
+Anyway, hope this was useful, happy configurating :)
diff --git a/content/posts/vanilla-javascript-theme-toggle-for-simpletons.md b/content/posts/vanilla-javascript-theme-toggle-for-simpletons.md
new file mode 100644
index 0000000..694ce24
--- /dev/null
+++ b/content/posts/vanilla-javascript-theme-toggle-for-simpletons.md
@@ -0,0 +1,120 @@
+---
+title: vanilla javascript theme toggle for simpletons
+date: 2023-06-26
+tags:
+ - javascript
+ - css
+draft: false
+---
+
+Sometimes when I'm trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I've been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you're looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.
+
+Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.
+
+### HTML
+
+First things first, we'll need a button for users to click. This can be plopped wherever you want on your site.
+
+```html
+
+```
+
+The `id` will let us reference the button from our javascript, `onclick` tells the button to call the `toggleTheme()` function we'll write in a minute, and the `theme-button` class will let us theme the button from our css.
+
+### CSS
+
+In order to achieve our magic theme switching we're going to split our css out in to three files: `base.css`, `dark.css`, and `light.css`. The `dark.css` and `light.css` files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple `dark.css` would look like this.
+
+```css
+/* import common css */
+@import url("base.css");
+
+/* define colors */
+:root {
+ --bg: black;
+ --fg: white;
+}
+```
+
+The `base.css` will simply store all the other styling you want. Here you can reference the color variables defined in the `dark.css` and `light.css`.
+
+```css
+body {
+ background-color: var(--bg);
+ color: var(--fg);
+}
+```
+
+### JS
+
+Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the `href` attribute of the `stylesheet` element. Then if it's set to `dark.css` switch it to `light.css` and vice-versa. my `toggleTheme` function looked like this.
+
+```javascript
+function toggleTheme() {
+
+ var stylesheet = document.getElementById('stylesheet');
+
+ if (stylesheet.getAttribute('href') === '/dark.css') {
+
+ // update stylesheet
+ stylesheet.setAttribute('href', '/light.css');
+
+ } else {
+
+ // update stylesheet
+ stylesheet.setAttribute('href', '/dark.css');
+
+ }
+}
+```
+
+This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.
+
+First we need to update our `toggleTheme` function to store our theme changes locally.
+
+```javascript
+function toggleTheme() {
+
+ var stylesheet = document.getElementById('stylesheet');
+
+ if (stylesheet.getAttribute('href') === '/dark.css') {
+
+ // update stylesheet
+ stylesheet.setAttribute('href', '/light.css');
+ // store theme
+ localStorage.setItem('stylesheet', '/light.css');
+
+ } else {
+
+ // update stylesheet
+ stylesheet.setAttribute('href', '/dark.css');
+ // store theme
+ localStorage.setItem('stylesheet', '/dark.css');
+
+ }
+}
+```
+
+We then add an event listener to check if there is a theme stored on page loads.
+
+```javascript
+window.addEventListener('load', function() {
+
+ // get stored style
+ var storedStyle = localStorage.getItem('stylesheet');
+ var stylesheet = document.getElementById('stylesheet');
+
+ // set stored style if it exists
+ if (storedStyle) {
+ stylesheet.setAttribute('href', storedStyle);
+ }
+});
+```
+
+Finally, don't forget to add your javascript to your html somewhere.
+
+```html
+
+```
+
+Hope you've enjoyed. Toggle toggle toggle!
diff --git a/content/posts/writing-a-qtile-widget.md b/content/posts/writing-a-qtile-widget.md
new file mode 100644
index 0000000..3758fb2
--- /dev/null
+++ b/content/posts/writing-a-qtile-widget.md
@@ -0,0 +1,137 @@
+---
+title: learning about qtile widgets via the medium of cricket
+date: 2023-04-03
+tags:
+ - qtile
+ - python
+draft: false
+---
+
+I'm a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.
+
+The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I'm sure this will interest very few people but I learnt some good stuff along the way.
+
+### Hello World?!
+
+As far as I can tell from looking at the code for some of the [built-in widgets](https://github.com/qtile/qtile/tree/master/libqtile/widget) and [this very helpful guide](https://docs.qtile.org/en/latest/manual/howto/widget.html), a basic hello world widget would look something like this.
+
+```python
+from libqtile.widget import base
+
+class HelloWorld(base._TextBox):
+ def __init__(self, **config):
+ super().__init__("", **config)
+ self.text = 'Hello world!'
+```
+
+Qtile provides a selection of base widget classes to do various useful things. This example uses the simple `_TextBox` which displays the content of the `self.text` property.
+
+### Hello World Version 2
+
+Very nice, but for the cricket widget we'll need something which lets us update the text. The answer is `ThreadPoolText`. This class lets you periodically update the text by overridding its `poll` method with a function that returns the updated text.
+
+This example updates itself with hello world in a different language every five seconds.
+
+```python
+import random
+
+class HolaMundo(base.ThreadPoolText):
+
+ defaults = [
+ ("update_interval", 5, "Update interval for the widget"),
+ ]
+
+ def __init__(self, **config):
+ super().__init__("", **config)
+ self.add_defaults(HolaMundo.defaults)
+
+ def poll(self):
+ messages = [
+ 'Hola mundo',
+ 'Ciao mondo',
+ 'مرحبا بالعالم',
+ 'Saluton Mondo',
+ 'Sawubona Mhlaba'
+ ]
+ return random.choice(messages)
+```
+
+Along with the whole poll thing, this example also introduces `defaults`. This is a list of tuples which define parameters that the user can configure. Here we've added `update_interval` which defines how often the widget is updated.
+
+### Cricket Scores
+
+For getting the cricket scores we'll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved [feedparser](https://pypi.org/project/feedparser/). This doesn't involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.
+
+```python
+from libqtile.widget import base
+import feedparser
+
+class CricketScores(base.ThreadPoolText):
+
+ defaults = [
+ ("update_interval", 60, "Update interval for the cricket scores widget"),
+ ("teams",[],"Teams to display scores for"),
+ ("separator"," \U0001F3CF ","Text to place between scores"),
+ ("no_scores_string","","Text to show when there are no scores to show"),
+ ]
+
+ def __init__(self, **config):
+ super().__init__("", **config)
+ self.add_defaults(CricketScores.defaults)
+
+ def get_scores(self):
+ # parse rss feed and get
+ # live matches from title field
+ feed = feedparser.parse("http://static.cricinfo.com/rss/livescores.xml")
+ scores = []
+ for match in feed.entries:
+ # filter live matches
+ if "*" in match.title:
+ scores.append(match.title)
+
+ # remove scores not involving chosen teams
+ filtered_scores = []
+ for score in scores:
+ for team in self.teams:
+ if team in score:
+ filtered_scores.append(score)
+
+ # if no scores, show no_scores_string
+ if len(filtered_scores) == 0:
+ return self.no_scores_string
+ else:
+ # form pretty string with separators
+ final_scores = ""
+ for score in filtered_scores:
+ if score != filtered_scores[-1]:
+ final_scores += score + self.separator
+ else:
+ final_scores += score
+ return final_scores
+
+ def poll(self):
+ return get_scores()
+```
+
+### Actaully Using It In Your Config
+
+Assuming you have a `my_widget.py` file in the same directory as your `config.py`, you simply have to import it and add it your list of widgets.
+
+```python
+from my_widget import LovelyWidget
+
+screens = [
+ Screen(
+ top = bar.Bar(
+ widgets = [
+ LovelyWidget(),
+ widget.GroupBox(),
+ ]
+ )
+ )
+]
+```
+
+Happy widget writing.
+
+
diff --git a/public/adventures-in-running-headscale-on-nixos/index.html b/public/adventures-in-running-headscale-on-nixos/index.html
new file mode 100644
index 0000000..0db8279
--- /dev/null
+++ b/public/adventures-in-running-headscale-on-nixos/index.html
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ adventures in running headscale on nixos
+
+
+
+
+
+
+
+
+
diff --git a/public/categories/index.html b/public/categories/index.html
new file mode 100644
index 0000000..3bd8c70
--- /dev/null
+++ b/public/categories/index.html
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Categories
+
+
+
+Categories
+
+
+
+
+
diff --git a/public/categories/index.xml b/public/categories/index.xml
new file mode 100644
index 0000000..2558acf
--- /dev/null
+++ b/public/categories/index.xml
@@ -0,0 +1,1415 @@
+
+
+
+ Categories on wretched.place
+ http://localhost:1313/categories/
+ Recent content in Categories on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
+
+
diff --git a/public/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/index.html b/public/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/index.html
new file mode 100644
index 0000000..efeaabf
--- /dev/null
+++ b/public/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/index.html
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ chess.com api and the continuing search for en passant checkmate
+
+
+
+
+ Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:
+
+Parse this info for the pgn (portable game notation) of each game.
+Write these to a file so we dont have to spend forever downloading them everytime we run the script.
+Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.
+
+First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.
+def get_pgns ( games ):
+ pgns = []
+ for game in games :
+ try :
+ pgn = game [ 'pgn' ]
+ pgns . append ( pgn )
+ except KeyError :
+ print ( 'key error um' )
+ return pgns
+ Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.
+def write_pgns ( pgns ):
+ with open ( month . replace ( '/' , '_' ) + '.csv' , 'w' ) as f :
+ for pgn in pgns :
+ f . write ( pgn )
+ Now a pgn looks something like this if it’s just printed as a string:
+
+It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:
+moves = [ 'e4' , 'e5' , 'Bc4' , 'Nc6' , 'Qh5' , 'Nf6' , 'Qxf7#' ]
+We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.
+def get_move_list ( pgn ):
+ x = pgn . split ()
+ moves = []
+ for item in x :
+ # start fresh list at move 1 - effectively skipping the headers from the list
+ if item == '1.' :
+ moves = []
+ moves . append ( item )
+ # gets rid of clock bits and bobs
+ elif item [ 0 ] == '{' or item [ - 1 ] == '}' :
+ pass
+ else :
+ moves . append ( item )
+ #remove even indexes from list
+ #this gets rid of move numbers and the result of the game
+ del moves [:: 2 ]
+ return moves
+ I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.
+
+
+
+
+
diff --git a/public/chess.com-api-and-the-search-for-en-passant-checkmate/index.html b/public/chess.com-api-and-the-search-for-en-passant-checkmate/index.html
new file mode 100644
index 0000000..94ddc02
--- /dev/null
+++ b/public/chess.com-api-and-the-search-for-en-passant-checkmate/index.html
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ chess.com api and the search for en passant checkmate
+
+
+
+
+ The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.
+First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with ->
+ def get_archive_urls ( titled_urls ):
+ players = []
+ for url in titled_urls :
+ title_list = requests . get ( url ) . json ()
+ title_list = title_list [ 'players' ]
+ players . extend ( title_list )
+
+ archive_urls = []
+ for username in players :
+ games = 'https://api.chess.com/pub/player/' + username + '/games/2022/05'
+ archive_urls . append ( games )
+ return archive_urls
+
+ get_archive_urls ([
+ 'https://api.chess.com/pub/titled/GM' ,
+ 'https://api.chess.com/pub/titled/WGM'
+ ])
+ This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.
+The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example ->
+ def grab_games ( archive_urls ):
+ games = []
+ for url in archive_urls :
+ archive = requests . get ( url ) . json ()
+ archive_games = archive [ 'games' ]
+ games . extend ( archive_games )
+ return games
+ Feeding the first function into the second ->
+ grab_games ( get_archive_urls ([
+ 'https://api.chess.com/pub/titled/GM' ,
+ 'https://api.chess.com/pub/titled/WGM'
+ ]))
+ We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.
+
+
+
+
+
+
diff --git a/public/css/style.min.css b/public/css/style.min.css
new file mode 100644
index 0000000..2453594
--- /dev/null
+++ b/public/css/style.min.css
@@ -0,0 +1 @@
+*,*:before,*:after{box-sizing:border-box}html{font-size:62.5%}body{font-size:16px;font-size:1.6rem;font-family:-apple-system,BlinkMacSystemFont,segoe ui,Helvetica,Arial,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol;color:#313a3d;width:100%;margin:0 auto;padding:0 16px;line-height:1.6;overflow-wrap:break-word}header#banner{margin:25px 0}header#banner a{color:#313a3d;text-decoration:none}header#banner a:hover{text-decoration:underline}header#banner h2{display:inline;font-size:21px;font-size:2.1rem;margin:0 8px 0 0}header#banner nav{display:inline-block}header#banner nav ul{list-style-type:none;font-size:1.05em;text-transform:lowercase;margin:0;padding:0}header#banner nav ul li{display:inline;margin:0 3px}header#banner nav ul li a{color:#454545}main#content a{color:#007dfa;text-decoration:none}main#content a:hover{text-decoration:underline}main#content h1,main#content h2,main#content h3,main#content h4,main#content h5,main#content h6{margin-bottom:0;line-height:1.15}main#content h3{font-size:19px;font-size:1.9rem}main#content h1+p,main#content h2+p,main#content h3+p,main#content h4+p,main#content h5+p,main#content h6+p{margin-top:5px}main#content p{color:#394548;margin:16px 0}main#content hr{height:1px;border:0;background:#d8d8d8}main#content abbr{cursor:help}main#content ul#posts{list-style-type:none;font-size:16px;font-size:1.6rem;margin-top:0;padding:0}main#content ul#posts li{margin:5px 0;padding:0}main#content ul#posts small{font-size:.8em;color:#767676;margin-left:10px}main#content ul#posts li a{text-decoration:none}main#content ul#posts li a:hover{color:#369aff}main#content ul#posts li a:hover small{color:inherit}main#content header#post-header h1{display:block;font-size:23px;font-size:2.3rem;font-weight:600;line-height:1.15}main#content header#post-header>div{display:block;font-size:.85em;color:#767676}main#content #toc{border:1px solid #b1b1b1;border-radius:1px;line-height:26px;margin:16px 0;padding:9px 14px}main#content #toc h4{font-size:1.06em;color:#3d3d3d;margin:0}main#content #toc nav#TableOfContents{margin-top:4px}main#content #toc nav#TableOfContents>ul,main#content #toc nav#TableOfContents>ol{margin-left:-40px}main#content #toc ul,main#content #toc ol{font-size:.98em;margin:0;padding:0 0 0 40px}main#content #toc ul{list-style-type:none}main#content #toc ol{counter-reset:item}main#content #toc ol li{display:block}main#content #toc ol li:before{content:counters(item,".")". ";counter-increment:item}main#content img{max-width:100%;margin:0 auto}main#content figure{margin:16px 0}main#content figure img{display:block;max-width:100%;margin:0 auto}main#content figure figcaption{font-size:.92em;font-style:italic;line-height:22px;text-align:center;margin-top:6px;padding:0 10px}main#content figure figcaption h4{font-style:normal;display:inline;margin:0}main#content figure figcaption p{display:inline;margin:0;padding-left:8px}main#content blockquote{font-style:italic;margin-top:10px;margin-bottom:10px;margin-left:50px;padding-left:15px;border-left:3px solid #ccc}main#content code,main#content pre{font-family:menlo,monospace}main#content code{font-size:.96em;padding:0 5px}main#content pre{display:block;overflow-x:auto;font-size:14px;font-size:1.4rem;white-space:pre;margin:20px 0;padding:1.5rem;line-height:1.4}main#content pre code{padding:0}main#content .footnotes{font-size:.9em}footer#footer{font-size:14px;font-size:1.4rem;font-weight:400;color:#b3b3b3;margin:40px 0}@media(min-width:770px){body{width:600px;line-height:1.5}main#content hr{width:108%;margin-left:-3.8%}header#banner h2{font-size:25px;font-size:2.5rem}main#content h3{font-size:20px;font-size:2rem}main#content ul#posts{font-size:18px;font-size:1.8rem}main#content header#post-header h1{font-size:24px;font-size:2.4rem}main#content img{max-width:108%;margin-left:-3.8%}main#content figure{margin-left:-3.8%}main#content figure img{max-width:108%}main#content pre{width:108%;margin-left:-3.8%;padding:1.5rem 2.2rem}}@media(prefers-color-scheme:dark){html{scrollbar-color:#6c6c6c #2e2e2e}body{color:#ebebeb;background:#121212;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}header#banner a{color:#e0e0e0;text-decoration:none}header#banner nav ul li a{color:#ccc}main#content a{color:#00b1ed}main#content p{color:#f5f5f5}main#content hr{background:#5c5c5c}main#content #toc h4{color:#d4d4d4}main#content ul#posts small{color:#a7a7a7}main#content ul#posts li a:hover{color:#21c7ff}main#content header#post-header div{color:#a7a7a7}}.chroma{color:#f8f8f2;background-color:#272822}.chroma .err{color:#960050;background-color:#1e0010}.chroma .lntd{vertical-align:top;padding:0;margin:0;border:0}.chroma .lntable{border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block}.chroma .hl{display:block;width:100%;background-color:#ffc}.chroma .lnt{margin-right:.4em;padding:0 .4em;color:#7f7f7f}.chroma .ln{margin-right:.4em;padding:0 .4em;color:#7f7f7f}.chroma .k{color:#66d9ef}.chroma .kc{color:#66d9ef}.chroma .kd{color:#66d9ef}.chroma .kn{color:#f92672}.chroma .kp{color:#66d9ef}.chroma .kr{color:#66d9ef}.chroma .kt{color:#66d9ef}.chroma .na{color:#a6e22e}.chroma .nc{color:#a6e22e}.chroma .no{color:#66d9ef}.chroma .nd{color:#a6e22e}.chroma .ne{color:#a6e22e}.chroma .nf{color:#a6e22e}.chroma .nx{color:#a6e22e}.chroma .nt{color:#f92672}.chroma .l{color:#ae81ff}.chroma .ld{color:#e6db74}.chroma .s{color:#e6db74}.chroma .sa{color:#e6db74}.chroma .sb{color:#e6db74}.chroma .sc{color:#e6db74}.chroma .dl{color:#e6db74}.chroma .sd{color:#e6db74}.chroma .s2{color:#e6db74}.chroma .se{color:#ae81ff}.chroma .sh{color:#e6db74}.chroma .si{color:#e6db74}.chroma .sx{color:#e6db74}.chroma .sr{color:#e6db74}.chroma .s1{color:#e6db74}.chroma .ss{color:#e6db74}.chroma .m{color:#ae81ff}.chroma .mb{color:#ae81ff}.chroma .mf{color:#ae81ff}.chroma .mh{color:#ae81ff}.chroma .mi{color:#ae81ff}.chroma .il{color:#ae81ff}.chroma .mo{color:#ae81ff}.chroma .o{color:#f92672}.chroma .ow{color:#f92672}.chroma .c{color:#75715e}.chroma .ch{color:#75715e}.chroma .cm{color:#75715e}.chroma .c1{color:#75715e}.chroma .cs{color:#75715e}.chroma .cp{color:#75715e}.chroma .cpf{color:#75715e}.chroma .gd{color:#f92672}.chroma .ge{font-style:italic}.chroma .gi{color:#a6e22e}.chroma .gs{font-weight:700}.chroma .gu{color:#75715e}
\ No newline at end of file
diff --git a/public/declarative-firefox-config-with-home-manager-on-nixos/index.html b/public/declarative-firefox-config-with-home-manager-on-nixos/index.html
new file mode 100644
index 0000000..dcd661c
--- /dev/null
+++ b/public/declarative-firefox-config-with-home-manager-on-nixos/index.html
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ declarative firefox config with home-manager on nixos
+
+
+
+
+ As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found this friendly githubber’s templates to be very helpful.
+First of all you’ll need to enable firefox with programs.firefox.enable = true;
+EXTENSIONS
+This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:
+{ pkgs , ... }:
+ let
+ addons = pkgs . nur . repos . rycee . firefox-addons ;
+ in
+ {
+ programs . firefox = {
+ extensions = with addons ; [
+ ublock-origin
+ bitwarden
+ darkreader
+ ];
+ };
+ }
+ This is the list of all extensions available in the repo.
+BOOKMARKS
+Bookmarks can be added per profile. The format for it goes something like this:
+profiles . james = {
+ bookmarks = [
+ {
+ name = "best website ever!" ;
+ url = "https://jdysmcl.xyz" ;
+ }
+ {
+ name = "best OS ever" ;
+ url = "https://nixos.org" ;
+ }
+ ];
+ };
+SETTINGS
+Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:
+profiles . james = {
+ settings = {
+ #newtab stuff
+ "browser.startup.homepage" = "https://searx.jdysmcl.xyz" ;
+ "browser.newtabpage.enabled" = false ;
+ "browser.newtabpage.activity-stream.enabled" = false ;
+
+ #some firefox features i don't really want
+ "extensions.pocket.enabled" = false ;
+ "extensions.formautofill.creditCards.enabled" = false ;
+ "identity.fxaccounts.enabled" = false ;
+ "signon.rememberSignons" = false ;
+ "browser.search.suggest.enabled" = false ;
+
+ #some privacy stuff
+ "privacy.resistFingerprinting" = true ;
+ "privacy.trackingprotection.enabled" = true ;
+ "dom.security.https_only_mode" = true ;
+ };
+ };
+Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out this or alternatively run a man home-configuration.nix. Hope this has been helpful :)
+
+
+
+
+
diff --git a/public/elite-bread-dough-for-lazy-boys/index.html b/public/elite-bread-dough-for-lazy-boys/index.html
new file mode 100644
index 0000000..21d742e
--- /dev/null
+++ b/public/elite-bread-dough-for-lazy-boys/index.html
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ elite bread dough for lazy boys
+
+
+
+
+ INGREDIENTI
+
+flour (ideally bread flour but if you don’t have it, it’s not the end of the world)
+water
+salt
+yeast (i use the little dried packet stuff)
+
+RATIOS
+To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:
+
+65% water
+2% salt
+0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)
+
+So if we used 1kg of flour for example, the recipe would look like this:
+
+1000g flour
+650g water
+20g salt
+5g yeast
+
+STEPS
+
+Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).
+Put in the fridge to slowly proof for at least a day.
+Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).
+Proof in vessel for an additional hour or so at room temperature.
+Bake!
+
+SOME HELPFUL RESOURCES
+
+
+
+
+
+
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..67b8d29
Binary files /dev/null and b/public/favicon.ico differ
diff --git a/public/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/index.html b/public/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/index.html
new file mode 100644
index 0000000..8b5cbc0
--- /dev/null
+++ b/public/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/index.html
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ get the thoughts out of your head and into a digital format with this python journal script
+
+
+
+
+ Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice org-journal package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.
+Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.
+WHAT’S THE TIME?
+First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:
+def whats_the_time ( format ):
+ return time . strftime ( format , time . localtime ( time . time ()))
+ This function takes a string using python date format codes and spits out the corresponding time. For example, '%A %d %B, %Y' would give you Wednesday 12 December, 2022.
+WHAT TO CALL THE FILES?
+My plan is to have three options for journal_frequency: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the journal_frequency that is set:
+def make_filename ():
+ if journal_frequency == 'daily' :
+ return whats_the_time ( '%Y%m %d ' ) + '.md'
+
+ elif journal_frequency == 'monthly' :
+ return whats_the_time ( '%Y%m' ) + '.md'
+
+ elif journal_frequency == 'yearly' :
+ return whats_the_time ( '%Y' ) + '.md'
+ DO WE NEED A NEW FILE?
+As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:
+def new_file_required ():
+ if os . path . exists ( os . path . join ( journal_dir , make_filename ())):
+ return False
+ else :
+ return True
+ MAKING FILES AND PUTTING THINGS IN THEM
+Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the title_string variable. This will be called when we do need a new file:
+def create_file ():
+ path = os . path . join ( journal_dir , make_filename ())
+ with open ( path , 'w' ) as f :
+ f . write ( '# ' + whats_the_time ( title_string ))
+ This guy adds a subheading wtih the current time as default using the entry_string variable. If you had journal_frequency set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.
+def write_date ():
+ path = os . path . join ( journal_dir , make_filename ())
+ with open ( path , 'a' ) as f :
+ f . write ( ' \n ' * 2 + '### ' + whats_the_time ( entry_string ))
+ OPENING A TEXT EDITOR
+Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and Popen . By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.
+def open_editor ():
+ cmd = [ editor , os . path . join ( journal_dir , make_filename ()) ]
+ process = subprocess . Popen ( cmd , stdout = subprocess . PIPE )
+ Now it’s just a matter of sticking all the functions together:
+def main ():
+ if new_file_required ():
+ create_file ()
+ write_date ()
+ open_editor ()
+ else :
+ write_date ()
+ open_editor ()
+
+ main ()
+As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script here atm. BYEBYE xxx
+
+
+
+
+
diff --git a/public/image/dropdown.png b/public/image/dropdown.png
new file mode 100644
index 0000000..d617a6e
Binary files /dev/null and b/public/image/dropdown.png differ
diff --git a/public/image/dropdown.webp b/public/image/dropdown.webp
new file mode 100644
index 0000000..95a2d89
Binary files /dev/null and b/public/image/dropdown.webp differ
diff --git a/public/image/dropdown2.png b/public/image/dropdown2.png
new file mode 100644
index 0000000..3f4d3cc
Binary files /dev/null and b/public/image/dropdown2.png differ
diff --git a/public/image/dropdown2.webp b/public/image/dropdown2.webp
new file mode 100644
index 0000000..4f9b7df
Binary files /dev/null and b/public/image/dropdown2.webp differ
diff --git a/public/image/emacs.png b/public/image/emacs.png
new file mode 100644
index 0000000..78f40e5
Binary files /dev/null and b/public/image/emacs.png differ
diff --git a/public/image/golazo.png b/public/image/golazo.png
new file mode 100644
index 0000000..eee6635
Binary files /dev/null and b/public/image/golazo.png differ
diff --git a/public/image/output.webp b/public/image/output.webp
new file mode 100644
index 0000000..f95ea91
Binary files /dev/null and b/public/image/output.webp differ
diff --git a/public/image/pgn.webp b/public/image/pgn.webp
new file mode 100644
index 0000000..a7bf25b
Binary files /dev/null and b/public/image/pgn.webp differ
diff --git a/public/index.html b/public/index.html
new file mode 100644
index 0000000..8a16bc0
--- /dev/null
+++ b/public/index.html
@@ -0,0 +1,186 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ wretched.place
+
+
+
+
+
+
+
+ adventures in running headscale on nixos
+ Jun 25, 2024
+
+
+
+
+
+ so you want to write a neovim plugin with lua
+ Apr 6, 2024
+
+
+
+
+
+ making nix-colors talk to neovim
+ Aug 18, 2023
+
+
+
+
+
+ vanilla javascript theme toggle for simpletons
+ Jun 26, 2023
+
+
+
+
+
+ tailscale, caddy, and nixos containers - a match made in heaven
+ May 16, 2023
+
+
+
+
+
+ learning about qtile widgets via the medium of cricket
+ Apr 3, 2023
+
+
+
+
+
+ theming nirvana
+ Mar 13, 2023
+
+
+
+
+
+ translating docker to nix?!
+ Feb 28, 2023
+
+
+
+
+
+ simple nixos config for vps static site
+ Jan 29, 2023
+
+
+
+
+
+ podcast setup for broke boys whose trash phone cant hack modern apps
+ Jan 24, 2023
+
+
+
+
+
+ elite bread dough for lazy boys
+ Jan 22, 2023
+
+
+
+
+
+ multi user qtile fiddling
+ Dec 20, 2022
+
+
+
+
+
+ teeny tiny bash fetch script
+ Dec 10, 2022
+
+
+
+
+
+ get the thoughts out of your head and into a digital format with this python journal script
+ Dec 1, 2022
+
+
+
+
+
+ lowkey emacs setup
+ Nov 18, 2022
+
+
+
+
+
+ setting up a lean mean hugo blogging theme
+ Nov 10, 2022
+
+
+
+
+
+ chess.com api and the continuing search for en passant checkmate
+ Nov 8, 2022
+
+
+
+
+
+ chess.com api and the search for en passant checkmate
+ Oct 26, 2022
+
+
+
+
+
+ declarative firefox config with home-manager on nixos
+ Oct 2, 2022
+
+
+
+
+
+ upgrade your qtile setup with a cute dropdown terminal
+ Sep 23, 2022
+
+
+
+
+
+ rudimentary local scrobbling with bash
+ Sep 13, 2022
+
+
+
+
+
+
+
+
+
diff --git a/public/index.xml b/public/index.xml
new file mode 100644
index 0000000..fa33e7f
--- /dev/null
+++ b/public/index.xml
@@ -0,0 +1,1425 @@
+
+
+
+ wretched.place
+ http://localhost:1313/
+ Recent content on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+ Tue, 25 Jun 2024 00:00:00 +0000
+
+
+
+
+
+ -
+
adventures in running headscale on nixos
+ http://localhost:1313/adventures-in-running-headscale-on-nixos/
+ Tue, 25 Jun 2024 00:00:00 +0000
+
+ http://localhost:1313/adventures-in-running-headscale-on-nixos/
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
diff --git a/public/info/index.html b/public/info/index.html
new file mode 100644
index 0000000..a60af70
--- /dev/null
+++ b/public/info/index.html
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This is a place to document bits and bobs I’ve been up to that have interested me.
+Expect linux and self-hosting tinkering, some novice programming, and maybe the occasional recipe.
+I tend to be a fool so take anything written here with a pinch of salt :)
+
+
+
+
+
diff --git a/public/learning-about-qtile-widgets-via-the-medium-of-cricket/index.html b/public/learning-about-qtile-widgets-via-the-medium-of-cricket/index.html
new file mode 100644
index 0000000..a386fd8
--- /dev/null
+++ b/public/learning-about-qtile-widgets-via-the-medium-of-cricket/index.html
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ learning about qtile widgets via the medium of cricket
+
+
+
+
+ I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.
+The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.
+Hello World?!
+As far as I can tell from looking at the code for some of the built-in widgets and this very helpful guide , a basic hello world widget would look something like this.
+from libqtile.widget import base
+
+ class HelloWorld ( base . _TextBox ):
+ def __init__ ( self , ** config ):
+ super () . __init__ ( "" , ** config )
+ self . text = 'Hello world!'
+ Qtile provides a selection of base widget classes to do various useful things. This example uses the simple _TextBox which displays the content of the self.text property.
+Hello World Version 2
+Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is ThreadPoolText. This class lets you periodically update the text by overridding its poll method with a function that returns the updated text.
+This example updates itself with hello world in a different language every five seconds.
+import random
+
+ class HolaMundo ( base . ThreadPoolText ):
+
+ defaults = [
+ ( "update_interval" , 5 , "Update interval for the widget" ),
+ ]
+
+ def __init__ ( self , ** config ):
+ super () . __init__ ( "" , ** config )
+ self . add_defaults ( HolaMundo . defaults )
+
+ def poll ( self ):
+ messages = [
+ 'Hola mundo' ,
+ 'Ciao mondo' ,
+ 'مرحبا بالعالم' ,
+ 'Saluton Mondo' ,
+ 'Sawubona Mhlaba'
+ ]
+ return random . choice ( messages )
+ Along with the whole poll thing, this example also introduces defaults. This is a list of tuples which define parameters that the user can configure. Here we’ve added update_interval which defines how often the widget is updated.
+Cricket Scores
+For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved feedparser . This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.
+from libqtile.widget import base
+import feedparser
+
+ class CricketScores ( base . ThreadPoolText ):
+
+ defaults = [
+ ( "update_interval" , 60 , "Update interval for the cricket scores widget" ),
+ ( "teams" ,[], "Teams to display scores for" ),
+ ( "separator" , " \U0001F3CF " , "Text to place between scores" ),
+ ( "no_scores_string" , "" , "Text to show when there are no scores to show" ),
+ ]
+
+ def __init__ ( self , ** config ):
+ super () . __init__ ( "" , ** config )
+ self . add_defaults ( CricketScores . defaults )
+
+ def get_scores ( self ):
+ # parse rss feed and get
+ # live matches from title field
+ feed = feedparser . parse ( "http://static.cricinfo.com/rss/livescores.xml" )
+ scores = []
+ for match in feed . entries :
+ # filter live matches
+ if "*" in match . title :
+ scores . append ( match . title )
+
+ # remove scores not involving chosen teams
+ filtered_scores = []
+ for score in scores :
+ for team in self . teams :
+ if team in score :
+ filtered_scores . append ( score )
+
+ # if no scores, show no_scores_string
+ if len ( filtered_scores ) == 0 :
+ return self . no_scores_string
+ else :
+ # form pretty string with separators
+ final_scores = ""
+ for score in filtered_scores :
+ if score != filtered_scores [ - 1 ]:
+ final_scores += score + self . separator
+ else :
+ final_scores += score
+ return final_scores
+
+ def poll ( self ):
+ return get_scores ()
+ Actaully Using It In Your Config
+Assuming you have a my_widget.py file in the same directory as your config.py, you simply have to import it and add it your list of widgets.
+from my_widget import LovelyWidget
+
+ screens = [
+ Screen (
+ top = bar . Bar (
+ widgets = [
+ LovelyWidget (),
+ widget . GroupBox (),
+ ]
+ )
+ )
+ ]
+Happy widget writing.
+
+
+
+
+
diff --git a/public/links/index.html b/public/links/index.html
new file mode 100644
index 0000000..7588723
--- /dev/null
+++ b/public/links/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ rss
+github
+matrix
+mastodon
+
+
+
+
+
diff --git a/public/lowkey-emacs-setup/index.html b/public/lowkey-emacs-setup/index.html
new file mode 100644
index 0000000..d399ce1
--- /dev/null
+++ b/public/lowkey-emacs-setup/index.html
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ lowkey emacs setup
+
+
+
+
+ About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.
+AESTHETIC NICETIES
+First things first, assuming you’re on linux emacs is configured with a file at ~/.emacs.d/init.el. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with M-x load-theme; if you want the setting to persist though you can add this to you init.el:
+( load-theme 'misterioso t )
+There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.
+Anyway we’ve got a theme, how about a custom startup message for our initial buffer:
+( setq inhibit-startup-message t
+ inhibit-startup-echo-area-message t
+ initial-scratch-message
+ ";;oh how i adore to edit text with emacs!" )
+ Maybe you dont want those big old cumbersome toolbars cluttering up your screen:
+( scroll-bar-mode -1 )
+( tool-bar-mode -1 )
+( menu-bar-mode -1 )
+Perhaps some line highlighting and numbering:
+;;line numbering
+( global-display-line-numbers-mode )
+( setq display-line-numbers-type 'relative )
+
+ ;;line higlight
+( global-hl-line-mode t )
+Custom font?
+( setq default-frame-alist ' (( font . "agave Nerd Font 14" )))
+CUSTOM KEYBINDINGS AND EVIL
+I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:
+( eval-when-compile
+ ( require 'use-package ))
+ These are the keybindings that I currently have going; nothing too crazy just a few simple things:
+( use-package evil
+ :config
+ ( evil-mode 1 )
+ ( evil-select-search-module 'evil-search-module 'evil-search )
+
+ ;;manage panes
+ ( define-key evil-normal-state-map ( kbd "M-s" ) 'evil-window-split )
+ ( define-key evil-normal-state-map ( kbd "M-v" ) 'evil-window-vsplit )
+
+ ( define-key evil-normal-state-map ( kbd "M-h" ) 'evil-window-left )
+ ( define-key evil-normal-state-map ( kbd "M-j" ) 'evil-window-down )
+ ( define-key evil-normal-state-map ( kbd "M-k" ) 'evil-window-up )
+ ( define-key evil-normal-state-map ( kbd "M-l" ) 'evil-window-right )
+
+ ;;get files open quick
+ ( define-key evil-normal-state-map ( kbd "M-f" ) 'find-file )
+ ( define-key evil-normal-state-map ( kbd "M-b" ) 'dired-jump )
+
+ ;;terminal
+ ( define-key evil-normal-state-map ( kbd "M-t" ) 'ansi-term )
+
+ ;;nav buffers
+ ( define-key evil-normal-state-map ( kbd "M-," ) ( kbd "C-x <left>" ))
+ ( define-key evil-normal-state-map ( kbd "M-." ) ( kbd "C-x <right>" ))
+ )
+ SOME FRIEDNLY IDE FEATURES YOU MAY LIKE
+I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:
+;; enable company in all buffers
+( add-hook 'after-init-hook 'global-company-mode )
+( use-package company
+ :commands company-tng-configure-default
+ :custom
+ ;; delay to start completion
+ ( company-idle-delay 0 )
+ ;; nb of chars before triggering completion
+ ( company-minimum-prefix-length 1 )
+ You want the nice little autopair brackets?
+( use-package flex-autopair
+ :config
+ ( flex-autopair-mode 1 ))
+ Clever commenting?
+( use-package smart-comment
+ :bind ( "M-c" . smart-comment ))
+ Here’s a little pic of the current setup :)
+
+
+
+
+
+
diff --git a/public/making-nix-colors-talk-to-neovim/index.html b/public/making-nix-colors-talk-to-neovim/index.html
new file mode 100644
index 0000000..e9418f3
--- /dev/null
+++ b/public/making-nix-colors-talk-to-neovim/index.html
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ making nix-colors talk to neovim
+
+
+
+
+ I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with nix-colors so that my neovim theme would follow color changes in home-manager.
+Luckily, I came across this handy little plugin from the lovely mini.nvim suite of plugins which lets you create your own theme with your custom colors.
+Beneath is a little snippet of how you could make it all happen.
+{ inputs , pkgs , ... }: {
+ imports = [
+ inputs . nix-colors . homeManagerModules . default
+ ];
+ scheme = inputs . nix-colors . schemes . onedark ;
+ programs . neovim = {
+ enable = true ;
+ plugins = with pkgs . vimPlugins ; [
+ {
+ plugin = mini-nvim ;
+ config = ''
+ lua << END
+ require('mini.base16').setup({
+ palette = {
+ base00 = '# ${ scheme . colors . base00 } ',
+ base01 = '# ${ scheme . colors . base01 } ',
+ base02 = '# ${ scheme . colors . base02 } ',
+ base03 = '# ${ scheme . colors . base03 } ',
+ base04 = '# ${ scheme . colors . base04 } ',
+ base05 = '# ${ scheme . colors . base05 } ',
+ base06 = '# ${ scheme . colors . base06 } ',
+ base07 = '# ${ scheme . colors . base07 } ',
+ base08 = '# ${ scheme . colors . base08 } ',
+ base09 = '# ${ scheme . colors . base09 } ',
+ base0A = '# ${ scheme . colors . base0A } ',
+ base0B = '# ${ scheme . colors . base0B } ',
+ base0C = '# ${ scheme . colors . base0C } ',
+ base0D = '# ${ scheme . colors . base0D } ',
+ base0E = '# ${ scheme . colors . base0E } ',
+ base0F = '# ${ scheme . colors . base0F } ',
+ },
+ })
+ END
+ '' ;
+ }
+ ];
+ };
+ }
+Happy theming!
+
+
+
+
+
diff --git a/public/multi-user-qtile-fiddling/index.html b/public/multi-user-qtile-fiddling/index.html
new file mode 100644
index 0000000..b99de95
--- /dev/null
+++ b/public/multi-user-qtile-fiddling/index.html
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ multi user qtile fiddling
+
+
+
+
+ This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using xdg.configFile. This is what I do with my qtile config.py. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.
+THE NUB OF THE PROBLEM
+I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:
+if socket . gethostname () == 'baron' :
+ # some stuff i want to happen on my desktop
+ elif socket . gethostname () == 'countess' :
+ # some stuff i want to happen on my laptop
+ There are three main things that I like to differ between my two computers:
+
+widgets on my bar (I don’t need brightness and battery on my desktop)
+keybindings
+programs to autostart
+
+
+My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).
+countess_widgets = [
+ # all the great widgets i want on my laptop
+ ]
+
+ screens = [
+ Screen (
+ top = bar . Bar (
+ widgets = countess_widgets
+ ),
+ ),
+ ]
+KEYBINDINGS
+For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.
+countess_keys = [
+ Key ([ m ], 'Up' ,
+ lazy . spawn ( 'light -A 5' ),
+ desc = 'backlight up'
+ ),
+ Key ([ m ], 'Down' ,
+ lazy . spawn ( 'light -U 5' ),
+ desc = 'backlight down'
+ ),
+ ]
+
+ keys . extend ( countess_keys )
+You could even change a specific global binding on one computer if you knew its index in the list:
+keys [ 420 ] = Key ([ m ], 'd' ,
+ lazy . spawn ( 'dmenu_run' ),
+ desc = 'dmenu'
+ )
+ AUTOSTART
+Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:
+@hook.subscribe.startup_once
+def autostart ():
+ processes = [
+ [
+ 'feh' ,
+ '--bg-scale' ,
+ '/home/james/pics/wallpapers/beaut.jpg'
+ ],
+ [
+ 'xrandr' ,
+ '--output' ,
+ 'DisplayPort2' ,
+ '--primary' ,
+ '--mode' ,
+ '1920x1080' ,
+ '--rate' ,
+ '143.85'
+ ]
+ ]
+ for p in processes :
+ subprocess . Popen ( p )
+ Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x
+
+
+
+
+
diff --git a/public/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/index.html b/public/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/index.html
new file mode 100644
index 0000000..c3f16f7
--- /dev/null
+++ b/public/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/index.html
@@ -0,0 +1,119 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ podcast setup for broke boys whose trash phone cant hack modern apps
+
+
+
+
+ I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:
+
+write python script to download podcasts
+set up cron job on my server to run script every couple of hours
+sync podcasts across my devices using the lovely syncthing
+listen to podcasts using vlc which my phone loves
+
+For the python script I used the lovely feedparser module for easy talking to my rss feeds.
+WHERE THE PODCASTS GO
+First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:
+rss_urls = [
+ 'https://anchor.fm/s/1311c8b8/podcast/rss' ,
+ 'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'
+ ]
+I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.
+def create_dirs ():
+ for url in rss_urls :
+ f = feedparser . parse ( url )
+ feed_name = f [ 'feed' ][ 'title' ]
+ current_feeds = os . listdir ( pod_dir )
+
+ if feed_name not in current_feeds :
+ os . makedirs ( pod_dir + feed_name )
+ DOWNLOADING
+With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.
+def get_pods ():
+ global feed_info
+ feed_info = []
+ for url in rss_urls :
+ f = feedparser . parse ( url )
+ for pod in f . entries :
+ if time . time () - time . mktime ( pod . published_parsed ) < ( 86400 * 7 ):
+ feed_name = f . feed . title
+ pod_name = pod . title
+ pod_dl = pod . enclosures [ 0 ] . href
+ pod_info = [
+ feed_name ,
+ pod_name ,
+ pod_dl
+ ]
+ feed_info . append ( pod_info )
+ return feed_info
+ This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.
+def get_downloads ():
+ downloads = []
+ pods = os . listdir ( pod_dir )
+
+ for dir in pods :
+ if os . path . isdir ( pod_dir + dir ):
+ for file in os . listdir ( pod_dir + dir ):
+ downloads . append ( file )
+ return downloads
+ Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.
+def download ():
+ a = get_pods ()
+ for pod in a :
+ b = get_downloads ()
+ if pod [ 1 ] + '.mp3' not in b :
+ try :
+ dl = requests . get ( pod [ 2 ])
+ except :
+ print ( 'Download Error' )
+
+ with open ( pod_dir + pod [ 0 ] + '/' + pod [ 1 ] + '.mp3' , 'wb' ) as file :
+ file . write ( dl . content )
+ PRUNING
+As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.
+def trim ():
+ for dir in os . listdir ( pod_dir ):
+ if os . path . isdir ( pod_dir + dir ):
+ pods = os . listdir ( pod_dir + dir )
+ for pod in pods :
+ st = os . stat ( pod_dir + dir + '/' + pod )
+ mtime = st . st_mtime
+ if time . time () - mtime > ( 86400 * trim_age ):
+ os . remove ( pod_dir + dir + '/' + pod )
+ The last thing is to call the functions:
+create_dirs ()
+download ()
+trim ()
+Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)
+
+
+
+
+
diff --git a/public/posts/index.html b/public/posts/index.html
new file mode 100644
index 0000000..b908bed
--- /dev/null
+++ b/public/posts/index.html
@@ -0,0 +1,173 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Posts
+
+
+
+
+
+ so you want to write a neovim plugin with lua
+ Apr 6, 2024
+
+
+
+
+
+ making nix-colors talk to neovim
+ Aug 18, 2023
+
+
+
+
+
+ vanilla javascript theme toggle for simpletons
+ Jun 26, 2023
+
+
+
+
+
+ tailscale, caddy, and nixos containers - a match made in heaven
+ May 16, 2023
+
+
+
+
+
+ learning about qtile widgets via the medium of cricket
+ Apr 3, 2023
+
+
+
+
+
+ theming nirvana
+ Mar 13, 2023
+
+
+
+
+
+ translating docker to nix?!
+ Feb 28, 2023
+
+
+
+
+
+ simple nixos config for vps static site
+ Jan 29, 2023
+
+
+
+
+
+ podcast setup for broke boys whose trash phone cant hack modern apps
+ Jan 24, 2023
+
+
+
+
+
+ elite bread dough for lazy boys
+ Jan 22, 2023
+
+
+
+
+
+ multi user qtile fiddling
+ Dec 20, 2022
+
+
+
+
+
+ teeny tiny bash fetch script
+ Dec 10, 2022
+
+
+
+
+
+ get the thoughts out of your head and into a digital format with this python journal script
+ Dec 1, 2022
+
+
+
+
+
+ lowkey emacs setup
+ Nov 18, 2022
+
+
+
+
+
+ setting up a lean mean hugo blogging theme
+ Nov 10, 2022
+
+
+
+
+
+ chess.com api and the continuing search for en passant checkmate
+ Nov 8, 2022
+
+
+
+
+
+ chess.com api and the search for en passant checkmate
+ Oct 26, 2022
+
+
+
+
+
+ declarative firefox config with home-manager on nixos
+ Oct 2, 2022
+
+
+
+
+
+ upgrade your qtile setup with a cute dropdown terminal
+ Sep 23, 2022
+
+
+
+
+
+ rudimentary local scrobbling with bash
+ Sep 13, 2022
+
+
+
+
+
+
+
+
diff --git a/public/posts/index.xml b/public/posts/index.xml
new file mode 100644
index 0000000..9bf83c3
--- /dev/null
+++ b/public/posts/index.xml
@@ -0,0 +1,1416 @@
+
+
+
+ Posts on wretched.place
+ http://localhost:1313/posts/
+ Recent content in Posts on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
+
+
diff --git a/public/rudimentary-local-scrobbling-with-bash/index.html b/public/rudimentary-local-scrobbling-with-bash/index.html
new file mode 100644
index 0000000..dff7dec
--- /dev/null
+++ b/public/rudimentary-local-scrobbling-with-bash/index.html
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ rudimentary local scrobbling with bash
+
+
+
+
+ There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.
+LET’S GET DOWN TO BUSINESS
+Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:
+/home/randy/music/Beyonce/Lemonade/
+To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:
+printf "%s" " $selected_path " | cut -c 18- >> scrobble
+As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.
+Abdullah Ibrahim/South Africa
+ Darkside/Psychic
+ SOPHIE/OIL OF EVERY PEARL' S UN-INSIDES
+ Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+ Townes Van Zandt
+ As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:
+tac scrobble | column -t -s "/" -N " ,artist,album,track"
+ Maybe you only want the last ten things you listened to:
+tail -n 10 scrobble | column -t -s "/" -N " ,artist,album,song"
+ To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:
+for album in $( awk -F/ '{ print $2 }' scrobble | sort -u)
+ do
+ echo "' $album '/" $( awk -F/ '{ print $2 }' " $scrob_file " | grep $album | wc -l) "" >> temp
+ done
+ So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.
+Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x
+
+
+
+
+
diff --git a/public/setting-up-a-lean-mean-hugo-blogging-theme/index.html b/public/setting-up-a-lean-mean-hugo-blogging-theme/index.html
new file mode 100644
index 0000000..2b54a0b
--- /dev/null
+++ b/public/setting-up-a-lean-mean-hugo-blogging-theme/index.html
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ setting up a lean mean hugo blogging theme
+
+
+
+
+ When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like hugo new site lovely-new-website, entered the new directory with cd lovely-new-website and you’ve got a selection of mostly empty directories looking something like this.
+.
+ ├── archetypes
+ │ └── default.md
+ ├── config.toml
+ ├── content
+ ├── data
+ ├── layouts
+ ├── public
+ ├── static
+ └── themes
+ Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend this guy which I used to get up and running. You could also check out my theme which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) git clone https://gitlab.com/robbygozzarder/mcl and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.
+The directory structure of your new theme will look something like this:
+.
+ └── mcl
+ ├── archetypes
+ │ └── default.md
+ ├── layouts
+ │ ├── 404.html
+ │ ├── _default
+ │ │ ├── list.html
+ │ │ └── single.html
+ │ ├── index.html
+ │ └── partials
+ │ ├── footer.html
+ │ ├── header.html
+ │ └── nav.html
+ ├── README.md
+ └── static
+ └── css
+ └── style.css
+ This is where most of the magic happens:
+
+The default.md file in the archetypes directory dictates what template to follow when adding new post files.
+The layouts directory is where most of the meat is:
+
+Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)
+Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.
+Partials also contains index.html which (you guessed it!) is your home page.
+
+
+Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).
+
+Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:
+
+Content is where you put your posts - these are just markdown files which hugo converts to html for you.
+Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl
+Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.
+
+Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:
+{{ partial "header.html" . }}
+
+ < p > This is mainly a place for me to document various
+bits and bobs I've been doing on my computers.
+ I am a noob in most things so take anything written
+ here with a pinch of salt. Lots of love :)</ p >
+
+ {{ .Content }}
+ {{ range .Site.RegularPages | first 5 }}
+ < h3 > < a href = "{{ .RelPermalink }}" > {{ .Title }}</ a ></ h3 >
+ {{ .Summary }}
+ < br >< br >
+ {{ .Date.Format "06 Jan, 2006" }} |
+ {{ .WordCount }} words |
+ {{ .ReadingTime }} mins |
+
+ {{ range (.GetTerms "tags") }}
+ < a href = '{{ .Permalink }}' > {{ .LinkTitle }}</ a >
+ {{ end }}
+
+ {{ end }}
+
+ {{ partial "footer.html" . }}
+ In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs here .
+
+
+
+
+
diff --git a/public/simple-nixos-config-for-vps-static-site/index.html b/public/simple-nixos-config-for-vps-static-site/index.html
new file mode 100644
index 0000000..55a3074
--- /dev/null
+++ b/public/simple-nixos-config-for-vps-static-site/index.html
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ simple nixos config for vps static site
+
+
+
+
+ Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.
+I’m going to go through a bit of the nixos config I’ve got for my vps.
+SSH
+Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.
+services . openssh = {
+ enable = true ;
+ ports = [ 69 ];
+ settings = {
+ passwordAuthentication = false ;
+ permitRootLogin = "no" ;
+ };
+ };
+ADDING A USER
+Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.
+users . users = {
+ ronald = {
+ isNormalUser = true ;
+ shell = pkgs . fish ;
+ extraGroups = [ "wheel" "nginx" ];
+ openssh . authorizedKeys . keyFiles = [ "/path/to/public/key/file" ]
+ };
+ };
+NGINX
+I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of /var/www/example-site at example-site.here. It also opens the ports for http and https in the firewall.
+services . nginx = {
+ enable = true ;
+ virtualHosts . "example-site.here" = {
+ enableACME = true ;
+ forceSSL = true ;
+ root = "/var/www/example-site/" ;
+ };
+ };
+networking . firewall . allowedTCPPorts = [ 80 443 ];
+HTTPS
+You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:
+security . acme = {
+ acceptTerms = true ;
+ defaults . email = "ronald@email.yes" ;
+ };
+This will set up certificates for any sites you set the enableAMCE to true option for.
+CRON
+This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.
+services . cron = {
+ enable = true ;
+ systemCronJobs = [
+ "@hourly root cp -r /home/ronald/example-site /var/www/"
+ ];
+ };
+This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.
+
+
+
+
+
diff --git a/public/sitemap.xml b/public/sitemap.xml
new file mode 100644
index 0000000..b475683
--- /dev/null
+++ b/public/sitemap.xml
@@ -0,0 +1,140 @@
+
+
+
+ http://localhost:1313/tags/lua/
+ 2024-04-06T00:00:00+00:00
+
+ http://localhost:1313/tags/neovim/
+ 2024-04-06T00:00:00+00:00
+
+ http://localhost:1313/posts/
+ 2024-04-06T00:00:00+00:00
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ 2024-04-06T00:00:00+00:00
+
+ http://localhost:1313/tags/
+ 2024-04-06T00:00:00+00:00
+
+ http://localhost:1313/
+ 2024-04-06T00:00:00+00:00
+
+ http://localhost:1313/tags/home-manager/
+ 2023-08-18T00:00:00+00:00
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ 2023-08-18T00:00:00+00:00
+
+ http://localhost:1313/tags/nix-colors/
+ 2023-08-18T00:00:00+00:00
+
+ http://localhost:1313/tags/nixos/
+ 2023-08-18T00:00:00+00:00
+
+ http://localhost:1313/tags/css/
+ 2023-06-26T00:00:00+00:00
+
+ http://localhost:1313/tags/javascript/
+ 2023-06-26T00:00:00+00:00
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ 2023-06-26T00:00:00+00:00
+
+ http://localhost:1313/tags/caddy/
+ 2023-05-16T00:00:00+00:00
+
+ http://localhost:1313/tags/self-hosting/
+ 2023-05-16T00:00:00+00:00
+
+ http://localhost:1313/tags/tailscale/
+ 2023-05-16T00:00:00+00:00
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ 2023-05-16T00:00:00+00:00
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ 2023-04-03T00:00:00+00:00
+
+ http://localhost:1313/tags/python/
+ 2023-04-03T00:00:00+00:00
+
+ http://localhost:1313/tags/qtile/
+ 2023-04-03T00:00:00+00:00
+
+ http://localhost:1313/theming-nirvana/
+ 2023-03-13T00:00:00+00:00
+
+ http://localhost:1313/tags/docker/
+ 2023-02-28T00:00:00+00:00
+
+ http://localhost:1313/tags/podman/
+ 2023-02-28T00:00:00+00:00
+
+ http://localhost:1313/translating-docker-to-nix/
+ 2023-02-28T00:00:00+00:00
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ 2023-01-29T00:00:00+00:00
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ 2023-01-24T00:00:00+00:00
+
+ http://localhost:1313/tags/cooking/
+ 2023-01-22T00:00:00+00:00
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ 2023-01-22T00:00:00+00:00
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ 2022-12-20T00:00:00+00:00
+
+ http://localhost:1313/tags/bash/
+ 2022-12-10T00:00:00+00:00
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ 2022-12-10T00:00:00+00:00
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ 2022-12-01T00:00:00+00:00
+
+ http://localhost:1313/tags/emacs/
+ 2022-11-18T00:00:00+00:00
+
+ http://localhost:1313/lowkey-emacs-setup/
+ 2022-11-18T00:00:00+00:00
+
+ http://localhost:1313/tags/hugo/
+ 2022-11-10T00:00:00+00:00
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ 2022-11-10T00:00:00+00:00
+
+ http://localhost:1313/tags/chess/
+ 2022-11-08T00:00:00+00:00
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ 2022-11-08T00:00:00+00:00
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ 2022-10-26T00:00:00+00:00
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ 2022-10-02T00:00:00+00:00
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ 2022-09-23T00:00:00+00:00
+
+ http://localhost:1313/tags/music/
+ 2022-09-13T00:00:00+00:00
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ 2022-09-13T00:00:00+00:00
+
+ http://localhost:1313/info/
+
+ http://localhost:1313/links/
+
+ http://localhost:1313/categories/
+
+
diff --git a/public/so-you-want-to-write-a-neovim-plugin-with-lua/index.html b/public/so-you-want-to-write-a-neovim-plugin-with-lua/index.html
new file mode 100644
index 0000000..9d97886
--- /dev/null
+++ b/public/so-you-want-to-write-a-neovim-plugin-with-lua/index.html
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ so you want to write a neovim plugin with lua
+
+
+
+
+ I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the official neovim docs which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.
+As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.
+This is what you will want your directory structure to look like.
+├── lua
+ │ └── note
+ │ └── init.lua
+ └── plugin
+ └── note.vim
+ The plugin/note.vim file will look like this.
+command ! Note lua require ( "note" ) .main ()
+This creates a custom command Note which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the lua/note/init.lua file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.
+First things first we create a plugin object.
+Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.
+local defaults = {
+ note_directory = "~/notes/" ,
+ date_format = "%Y-%m-%d %H:%M" ,
+ file_extension = ".md" ,
+ }
+Next we need the setup function.
+This takes the user’s options and merges them with our default options.
+function note . setup ( user_options )
+ options = vim.tbl_deep_extend ( "force" , defaults , user_options or {})
+ end
+This is the main function where the magic happens.
+function note . main ()
+ local dir = options.note_directory
+ local name = os.date ( options.date_format )
+ local ext = options.file_extension
+ local filename = string.format ( "%s%s%s" , dir , name , ext )
+ local command = string.format ( "edit %s" , filename )
+ vim.api . nvim_command ( command )
+ end
+Finally we return the plugin obect.
+At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using lazy.nvim .
+require ( "lazy" ). setup ({
+ {
+ -- local
+ dir = "~/neovim-note-plugin" ,
+
+ -- github
+ -- "me/neovim-note-plugin",
+
+ -- alternative non github hosting
+ -- url = "https://git.example.com/me/neovim note-plugin",
+
+ config = fucntion ()
+ require ( "note" ). setup ({
+ file_extension = ".org" ,
+ })
+ end ,
+
+ }
+ })
+Hope you’ve enjoyed.
+
+
+
+
+
diff --git a/public/tags/bash/index.html b/public/tags/bash/index.html
new file mode 100644
index 0000000..8111be4
--- /dev/null
+++ b/public/tags/bash/index.html
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Bash
+
+
+
+Bash
+
+
+
+
+
diff --git a/public/tags/bash/index.xml b/public/tags/bash/index.xml
new file mode 100644
index 0000000..4167320
--- /dev/null
+++ b/public/tags/bash/index.xml
@@ -0,0 +1,1416 @@
+
+
+
+ Bash on wretched.place
+ http://localhost:1313/tags/bash/
+ Recent content in Bash on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
+
+
diff --git a/public/tags/caddy/index.html b/public/tags/caddy/index.html
new file mode 100644
index 0000000..85b357e
--- /dev/null
+++ b/public/tags/caddy/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Caddy
+
+
+
+Caddy
+
+
+
+
+
diff --git a/public/tags/caddy/index.xml b/public/tags/caddy/index.xml
new file mode 100644
index 0000000..7370f5f
--- /dev/null
+++ b/public/tags/caddy/index.xml
@@ -0,0 +1,1416 @@
+
+
+
+ Caddy on wretched.place
+ http://localhost:1313/tags/caddy/
+ Recent content in Caddy on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+ Tue, 16 May 2023 00:00:00 +0000
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
+
+
diff --git a/public/tags/chess/index.html b/public/tags/chess/index.html
new file mode 100644
index 0000000..f3da3a1
--- /dev/null
+++ b/public/tags/chess/index.html
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Chess
+
+
+
+Chess
+
+
+
+
+
diff --git a/public/tags/chess/index.xml b/public/tags/chess/index.xml
new file mode 100644
index 0000000..01d1783
--- /dev/null
+++ b/public/tags/chess/index.xml
@@ -0,0 +1,1416 @@
+
+
+
+ Chess on wretched.place
+ http://localhost:1313/tags/chess/
+ Recent content in Chess on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
+
+
diff --git a/public/tags/cooking/index.html b/public/tags/cooking/index.html
new file mode 100644
index 0000000..65e9b9b
--- /dev/null
+++ b/public/tags/cooking/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Cooking
+
+
+
+Cooking
+
+
+
+
+
diff --git a/public/tags/cooking/index.xml b/public/tags/cooking/index.xml
new file mode 100644
index 0000000..966f4bd
--- /dev/null
+++ b/public/tags/cooking/index.xml
@@ -0,0 +1,1416 @@
+
+
+
+ Cooking on wretched.place
+ http://localhost:1313/tags/cooking/
+ Recent content in Cooking on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
+
+
diff --git a/public/tags/css/index.html b/public/tags/css/index.html
new file mode 100644
index 0000000..ba26f0f
--- /dev/null
+++ b/public/tags/css/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Css
+
+
+
+Css
+
+
+
+
+
diff --git a/public/tags/css/index.xml b/public/tags/css/index.xml
new file mode 100644
index 0000000..cf40854
--- /dev/null
+++ b/public/tags/css/index.xml
@@ -0,0 +1,1416 @@
+
+
+
+ Css on wretched.place
+ http://localhost:1313/tags/css/
+ Recent content in Css on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
+
+
diff --git a/public/tags/docker/index.html b/public/tags/docker/index.html
new file mode 100644
index 0000000..5b3888a
--- /dev/null
+++ b/public/tags/docker/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Docker
+
+
+
+Docker
+
+
+
+
+
diff --git a/public/tags/docker/index.xml b/public/tags/docker/index.xml
new file mode 100644
index 0000000..cba09c5
--- /dev/null
+++ b/public/tags/docker/index.xml
@@ -0,0 +1,1416 @@
+
+
+
+ Docker on wretched.place
+ http://localhost:1313/tags/docker/
+ Recent content in Docker on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
+
+
diff --git a/public/tags/emacs/index.html b/public/tags/emacs/index.html
new file mode 100644
index 0000000..5f91cdb
--- /dev/null
+++ b/public/tags/emacs/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Emacs
+
+
+
+Emacs
+
+
+
+
+
diff --git a/public/tags/emacs/index.xml b/public/tags/emacs/index.xml
new file mode 100644
index 0000000..f00ac09
--- /dev/null
+++ b/public/tags/emacs/index.xml
@@ -0,0 +1,1416 @@
+
+
+
+ Emacs on wretched.place
+ http://localhost:1313/tags/emacs/
+ Recent content in Emacs on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
+
+
diff --git a/public/tags/home-manager/index.html b/public/tags/home-manager/index.html
new file mode 100644
index 0000000..83b1b32
--- /dev/null
+++ b/public/tags/home-manager/index.html
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Home-Manager
+
+
+
+Home-Manager
+
+
+
+
+
diff --git a/public/tags/home-manager/index.xml b/public/tags/home-manager/index.xml
new file mode 100644
index 0000000..67c7c01
--- /dev/null
+++ b/public/tags/home-manager/index.xml
@@ -0,0 +1,1416 @@
+
+
+
+ Home-Manager on wretched.place
+ http://localhost:1313/tags/home-manager/
+ Recent content in Home-Manager on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
+
+
diff --git a/public/tags/hugo/index.html b/public/tags/hugo/index.html
new file mode 100644
index 0000000..1b8ac49
--- /dev/null
+++ b/public/tags/hugo/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Hugo
+
+
+
+Hugo
+
+
+
+
+
diff --git a/public/tags/hugo/index.xml b/public/tags/hugo/index.xml
new file mode 100644
index 0000000..c060211
--- /dev/null
+++ b/public/tags/hugo/index.xml
@@ -0,0 +1,1416 @@
+
+
+
+ Hugo on wretched.place
+ http://localhost:1313/tags/hugo/
+ Recent content in Hugo on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
+
+
diff --git a/public/tags/index.html b/public/tags/index.html
new file mode 100644
index 0000000..e04d784
--- /dev/null
+++ b/public/tags/index.html
@@ -0,0 +1,175 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Tags
+
+
+
+Tags
+
+
+
+ Lua
+ Apr 6, 2024
+
+
+
+
+
+ Neovim
+ Apr 6, 2024
+
+
+
+
+
+ Home-Manager
+ Aug 18, 2023
+
+
+
+
+
+ Nix-Colors
+ Aug 18, 2023
+
+
+
+
+
+ Nixos
+ Aug 18, 2023
+
+
+
+
+
+ Css
+ Jun 26, 2023
+
+
+
+
+
+ Javascript
+ Jun 26, 2023
+
+
+
+
+
+ Caddy
+ May 16, 2023
+
+
+
+
+
+ Self-Hosting
+ May 16, 2023
+
+
+
+
+
+ Tailscale
+ May 16, 2023
+
+
+
+
+
+ Python
+ Apr 3, 2023
+
+
+
+
+
+ Qtile
+ Apr 3, 2023
+
+
+
+
+
+ Docker
+ Feb 28, 2023
+
+
+
+
+
+ Podman
+ Feb 28, 2023
+
+
+
+
+
+ Cooking
+ Jan 22, 2023
+
+
+
+
+
+ Bash
+ Dec 10, 2022
+
+
+
+
+
+ Emacs
+ Nov 18, 2022
+
+
+
+
+
+ Hugo
+ Nov 10, 2022
+
+
+
+
+
+ Chess
+ Nov 8, 2022
+
+
+
+
+
+ Music
+ Sep 13, 2022
+
+
+
+
+
+
+
+
diff --git a/public/tags/index.xml b/public/tags/index.xml
new file mode 100644
index 0000000..058cdce
--- /dev/null
+++ b/public/tags/index.xml
@@ -0,0 +1,1416 @@
+
+
+
+ Tags on wretched.place
+ http://localhost:1313/tags/
+ Recent content in Tags on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
+
+
diff --git a/public/tags/javascript/index.html b/public/tags/javascript/index.html
new file mode 100644
index 0000000..4cee6c4
--- /dev/null
+++ b/public/tags/javascript/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Javascript
+
+
+
+Javascript
+
+
+
+
+
diff --git a/public/tags/javascript/index.xml b/public/tags/javascript/index.xml
new file mode 100644
index 0000000..26d887f
--- /dev/null
+++ b/public/tags/javascript/index.xml
@@ -0,0 +1,1416 @@
+
+
+
+ Javascript on wretched.place
+ http://localhost:1313/tags/javascript/
+ Recent content in Javascript on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
+
+
diff --git a/public/tags/lua/index.html b/public/tags/lua/index.html
new file mode 100644
index 0000000..ee40bca
--- /dev/null
+++ b/public/tags/lua/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Lua
+
+
+
+Lua
+
+
+
+
+
diff --git a/public/tags/lua/index.xml b/public/tags/lua/index.xml
new file mode 100644
index 0000000..2784c5e
--- /dev/null
+++ b/public/tags/lua/index.xml
@@ -0,0 +1,1416 @@
+
+
+
+ Lua on wretched.place
+ http://localhost:1313/tags/lua/
+ Recent content in Lua on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
+
+
diff --git a/public/tags/music/index.html b/public/tags/music/index.html
new file mode 100644
index 0000000..c3c9190
--- /dev/null
+++ b/public/tags/music/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Music
+
+
+
+Music
+
+
+
+
+
diff --git a/public/tags/music/index.xml b/public/tags/music/index.xml
new file mode 100644
index 0000000..ab0109e
--- /dev/null
+++ b/public/tags/music/index.xml
@@ -0,0 +1,1416 @@
+
+
+
+ Music on wretched.place
+ http://localhost:1313/tags/music/
+ Recent content in Music on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
+
+
diff --git a/public/tags/neovim/index.html b/public/tags/neovim/index.html
new file mode 100644
index 0000000..f2ce4de
--- /dev/null
+++ b/public/tags/neovim/index.html
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Neovim
+
+
+
+Neovim
+
+
+
+
+
diff --git a/public/tags/neovim/index.xml b/public/tags/neovim/index.xml
new file mode 100644
index 0000000..acb1c56
--- /dev/null
+++ b/public/tags/neovim/index.xml
@@ -0,0 +1,1416 @@
+
+
+
+ Neovim on wretched.place
+ http://localhost:1313/tags/neovim/
+ Recent content in Neovim on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
+
+
diff --git a/public/tags/nix-colors/index.html b/public/tags/nix-colors/index.html
new file mode 100644
index 0000000..09cea72
--- /dev/null
+++ b/public/tags/nix-colors/index.html
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Nix-Colors
+
+
+
+Nix-Colors
+
+
+
+
+
diff --git a/public/tags/nix-colors/index.xml b/public/tags/nix-colors/index.xml
new file mode 100644
index 0000000..1953b8b
--- /dev/null
+++ b/public/tags/nix-colors/index.xml
@@ -0,0 +1,1416 @@
+
+
+
+ Nix-Colors on wretched.place
+ http://localhost:1313/tags/nix-colors/
+ Recent content in Nix-Colors on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
+
+
diff --git a/public/tags/nixos/index.html b/public/tags/nixos/index.html
new file mode 100644
index 0000000..9ca8278
--- /dev/null
+++ b/public/tags/nixos/index.html
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Nixos
+
+
+
+Nixos
+
+
+
+
+
diff --git a/public/tags/nixos/index.xml b/public/tags/nixos/index.xml
new file mode 100644
index 0000000..c074765
--- /dev/null
+++ b/public/tags/nixos/index.xml
@@ -0,0 +1,1416 @@
+
+
+
+ Nixos on wretched.place
+ http://localhost:1313/tags/nixos/
+ Recent content in Nixos on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
+
+
diff --git a/public/tags/podman/index.html b/public/tags/podman/index.html
new file mode 100644
index 0000000..b2a1848
--- /dev/null
+++ b/public/tags/podman/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Podman
+
+
+
+Podman
+
+
+
+
+
diff --git a/public/tags/podman/index.xml b/public/tags/podman/index.xml
new file mode 100644
index 0000000..d81ff76
--- /dev/null
+++ b/public/tags/podman/index.xml
@@ -0,0 +1,1416 @@
+
+
+
+ Podman on wretched.place
+ http://localhost:1313/tags/podman/
+ Recent content in Podman on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
+
+
diff --git a/public/tags/python/index.html b/public/tags/python/index.html
new file mode 100644
index 0000000..8d6630d
--- /dev/null
+++ b/public/tags/python/index.html
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Python
+
+
+
+Python
+
+
+
+
+
diff --git a/public/tags/python/index.xml b/public/tags/python/index.xml
new file mode 100644
index 0000000..156fb2b
--- /dev/null
+++ b/public/tags/python/index.xml
@@ -0,0 +1,1416 @@
+
+
+
+ Python on wretched.place
+ http://localhost:1313/tags/python/
+ Recent content in Python on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
+
+
diff --git a/public/tags/qtile/index.html b/public/tags/qtile/index.html
new file mode 100644
index 0000000..7c438c5
--- /dev/null
+++ b/public/tags/qtile/index.html
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Qtile
+
+
+
+Qtile
+
+
+
+
+
diff --git a/public/tags/qtile/index.xml b/public/tags/qtile/index.xml
new file mode 100644
index 0000000..dd0ca87
--- /dev/null
+++ b/public/tags/qtile/index.xml
@@ -0,0 +1,1416 @@
+
+
+
+ Qtile on wretched.place
+ http://localhost:1313/tags/qtile/
+ Recent content in Qtile on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
+
+
diff --git a/public/tags/self-hosting/index.html b/public/tags/self-hosting/index.html
new file mode 100644
index 0000000..32bfc3f
--- /dev/null
+++ b/public/tags/self-hosting/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Self-Hosting
+
+
+
+Self-Hosting
+
+
+
+
+
diff --git a/public/tags/self-hosting/index.xml b/public/tags/self-hosting/index.xml
new file mode 100644
index 0000000..11a6a75
--- /dev/null
+++ b/public/tags/self-hosting/index.xml
@@ -0,0 +1,1416 @@
+
+
+
+ Self-Hosting on wretched.place
+ http://localhost:1313/tags/self-hosting/
+ Recent content in Self-Hosting on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+ Tue, 16 May 2023 00:00:00 +0000
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
+
+
diff --git a/public/tags/tailscale/index.html b/public/tags/tailscale/index.html
new file mode 100644
index 0000000..fa509f2
--- /dev/null
+++ b/public/tags/tailscale/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Tailscale
+
+
+
+Tailscale
+
+
+
+
+
diff --git a/public/tags/tailscale/index.xml b/public/tags/tailscale/index.xml
new file mode 100644
index 0000000..54b77a0
--- /dev/null
+++ b/public/tags/tailscale/index.xml
@@ -0,0 +1,1416 @@
+
+
+
+ Tailscale on wretched.place
+ http://localhost:1313/tags/tailscale/
+ Recent content in Tailscale on wretched.place
+ Hugo -- gohugo.io
+ en-GB
+ Tue, 16 May 2023 00:00:00 +0000
+
+
+
+
+
+ -
+
so you want to write a neovim plugin with lua
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ Sat, 06 Apr 2024 00:00:00 +0000
+
+ http://localhost:1313/so-you-want-to-write-a-neovim-plugin-with-lua/
+ <p>I’ve recently been messing around with writing neovim plugins.
+When I initially got going I found it a little tricky to know how to get started.
+There’s the <a href="https://neovim.io/doc">official neovim docs</a> which are great; but in my beginner experience exhaustive to the point of slight impenetrability.
+Beyond that, the thing I found most useful was simply reading the source of some popular plugins to get an idea of how things worked.
+I would recommend sticking to plugins with a smaller scope though.</p>
+<p>As a demostrative MVP (minimal viable plugin) jumping-off-point, I’m going to make a very simple note-taking plugin.
+It will provide a command to neovim which when run opens a file titled with the date and time in a specific notes directory.
+Vamos.</p>
+<p>This is what you will want your directory structure to look like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">├── lua
+</span></span><span class="line"><span class="cl">│ └── note
+</span></span><span class="line"><span class="cl">│ └── init.lua
+</span></span><span class="line"><span class="cl">└── plugin
+</span></span><span class="line"><span class="cl"> └── note.vim
+</span></span></code></pre></div><p>The <code>plugin/note.vim</code> file will look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-vim" data-lang="vim"><span class="line"><span class="cl"><span class="nx">command</span><span class="p">!</span> <span class="nx">Note</span> <span class="nx">lua</span> <span class="nx">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">)</span>.<span class="nx">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>This creates a custom command <code>Note</code> which when run will call a lua function.
+Now on to where that function and the meat of the plugin logic will live: the <code>lua/note/init.lua</code> file.
+With more complex plugins this section will often be split into many files but we’ve just got one here as it’s so simple.</p>
+<p>First things first we create a plugin object.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">note</span> <span class="o">=</span> <span class="p">{}</span>
+</span></span></code></pre></div><p>Then we will define some default options for the plugin in a table.
+These are variables you want the user to be able to change when they call the setup function.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">note_directory</span> <span class="o">=</span> <span class="s2">"~/notes/"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">date_format</span> <span class="o">=</span> <span class="s2">"%Y-%m-%d %H:%M"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".md"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Next we need the setup function.
+This takes the user’s options and merges them with our default options.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">setup</span><span class="p">(</span><span class="n">user_options</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">options</span> <span class="o">=</span> <span class="n">vim.tbl_deep_extend</span><span class="p">(</span><span class="s2">"force"</span><span class="p">,</span> <span class="n">defaults</span><span class="p">,</span> <span class="n">user_options</span> <span class="ow">or</span> <span class="p">{})</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>This is the main function where the magic happens.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">function</span> <span class="nc">note</span><span class="p">.</span><span class="nf">main</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">dir</span> <span class="o">=</span> <span class="n">options.note_directory</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">name</span> <span class="o">=</span> <span class="n">os.date</span><span class="p">(</span><span class="n">options.date_format</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">options.file_extension</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">filename</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"%s%s%s"</span><span class="p">,</span> <span class="n">dir</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">local</span> <span class="n">command</span> <span class="o">=</span> <span class="n">string.format</span><span class="p">(</span><span class="s2">"edit %s"</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">vim.api</span><span class="p">.</span><span class="n">nvim_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="kr">end</span>
+</span></span></code></pre></div><p>Finally we return the plugin obect.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="kr">return</span> <span class="n">note</span>
+</span></span></code></pre></div><p>At this point you should have a working plugin :)
+As a little coda, this is how you can use your fancy new plugin using <a href="https://github.com/folke/lazy.nvim/">lazy.nvim</a>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">require</span><span class="p">(</span><span class="s2">"lazy"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- local</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dir</span> <span class="o">=</span> <span class="s2">"~/neovim-note-plugin"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- github</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- "me/neovim-note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">-- alternative non github hosting</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">-- url = "https://git.example.com/me/neovim note-plugin",</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="n">fucntion</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">require</span><span class="p">(</span><span class="s2">"note"</span><span class="p">).</span><span class="n">setup</span><span class="p">({</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file_extension</span> <span class="o">=</span> <span class="s2">".org"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">})</span>
+</span></span><span class="line"><span class="cl"> <span class="kr">end</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">})</span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed.</p>
+
+
+
+
+
+ -
+
making nix-colors talk to neovim
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ Fri, 18 Aug 2023 00:00:00 +0000
+
+ http://localhost:1313/making-nix-colors-talk-to-neovim/
+ <p>I recently started fiddling around with home-managerifying my neovim config.
+After moving across most of my stuff I came across the problem of how to hook things up with with <a href="https://github.com/misterio77/nix-colors">nix-colors</a> so that my neovim theme would follow color changes in home-manager.</p>
+<p>Luckily, I came across <a href="https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-base16.md">this</a> handy little plugin from the lovely <a href="https://github.com/echasnovski/mini.nvim">mini.nvim</a> suite of plugins which lets you create your own theme with your custom colors.</p>
+<p>Beneath is a little snippet of how you could make it all happen.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">inputs</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModules</span><span class="o">.</span><span class="n">default</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scheme</span> <span class="o">=</span> <span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">schemes</span><span class="o">.</span><span class="n">onedark</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">neovim</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugins</span> <span class="o">=</span> <span class="k">with</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">vimPlugins</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">plugin</span> <span class="o">=</span> <span class="n">mini-nvim</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> lua << END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> require('mini.base16').setup({
+</span></span></span><span class="line"><span class="cl"><span class="s1"> palette = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base00 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base00</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base01 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base02 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base02</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base03 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base03</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base04 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base04</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base05 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base06 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base06</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base07 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base07</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base08 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base09 = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0A = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0B = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0C = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0D = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0E = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> base0F = '#</span><span class="si">${</span><span class="n">scheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">',
+</span></span></span><span class="line"><span class="cl"><span class="s1"> },
+</span></span></span><span class="line"><span class="cl"><span class="s1"> })
+</span></span></span><span class="line"><span class="cl"><span class="s1"> END
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Happy theming!</p>
+
+
+
+
+
+ -
+
vanilla javascript theme toggle for simpletons
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ Mon, 26 Jun 2023 00:00:00 +0000
+
+ http://localhost:1313/vanilla-javascript-theme-toggle-for-simpletons/
+ <p>Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.</p>
+<p>Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.</p>
+<h3 id="html">HTML</h3>
+<p>First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">"themeButton"</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"toggleTheme()"</span> <span class="na">class</span><span class="o">=</span><span class="s">"theme-button"</span><span class="p">></span>
+</span></span></code></pre></div><p>The <code>id</code> will let us reference the button from our javascript, <code>onclick</code> tells the button to call the <code>toggleTheme()</code> function we’ll write in a minute, and the <code>theme-button</code> class will let us theme the button from our css.</p>
+<h3 id="css">CSS</h3>
+<p>In order to achieve our magic theme switching we’re going to split our css out in to three files: <code>base.css</code>, <code>dark.css</code>, and <code>light.css</code>. The <code>dark.css</code> and <code>light.css</code> files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple <code>dark.css</code> would look like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="c">/* import common css */</span>
+</span></span><span class="line"><span class="cl"><span class="p">@</span><span class="k">import</span> <span class="nt">url</span><span class="o">(</span><span class="s2">"base.css"</span><span class="o">)</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c">/* define colors */</span>
+</span></span><span class="line"><span class="cl"><span class="p">:</span><span class="nd">root</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--bg</span><span class="p">:</span> <span class="kc">black</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">--fg</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>The <code>base.css</code> will simply store all the other styling you want. Here you can reference the color variables defined in the <code>dark.css</code> and <code>light.css</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="cl"><span class="nt">body</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="k">background-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">bg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="k">color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">fg</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="js">JS</h3>
+<p>Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the <code>href</code> attribute of the <code>stylesheet</code> element. Then if it’s set to <code>dark.css</code> switch it to <code>light.css</code> and vice-versa. my <code>toggleTheme</code> function looked like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.</p>
+<p>First we need to update our <code>toggleTheme</code> function to store our theme changes locally.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">toggleTheme</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="nx">stylesheet</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'/dark.css'</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/light.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// update stylesheet
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">// store theme
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">setItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">,</span> <span class="s1">'/dark.css'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>We then add an event listener to check if there is a theme stored on page loads.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'load'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// get stored style
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="kd">var</span> <span class="nx">storedStyle</span> <span class="o">=</span> <span class="nx">localStorage</span><span class="p">.</span><span class="nx">getItem</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">stylesheet</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'stylesheet'</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">// set stored style if it exists
+</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="k">if</span> <span class="p">(</span><span class="nx">storedStyle</span><span class="p">)</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nx">stylesheet</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'href'</span><span class="p">,</span> <span class="nx">storedStyle</span><span class="p">);</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"><span class="p">});</span>
+</span></span></code></pre></div><p>Finally, don’t forget to add your javascript to your html somewhere.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"/toggle.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
+</span></span></code></pre></div><p>Hope you’ve enjoyed. Toggle toggle toggle!</p>
+
+
+
+
+
+ -
+
tailscale, caddy, and nixos containers - a match made in heaven
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ Tue, 16 May 2023 00:00:00 +0000
+
+ http://localhost:1313/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/
+ <p>For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity <a href="https://tailscale.com/">tailscale</a> brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.</p>
+<p>When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across <a href="https://caddy.community/t/https-in-your-vpn-caddy-now-uses-tls-certificates-from-tailscale/15380">this</a>. This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.</p>
+<h3 id="what-to-do">what to do?</h3>
+<p>Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One <a href="https://nixos.wiki/wiki/NixOS_Containers">nixos-container</a> for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">nat</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">internalInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"ve-+"</span><span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">externalInterface</span> <span class="o">=</span> <span class="s2">"ens3"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">containers</span><span class="o">.</span><span class="n">jellyfin</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableTun</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">privateNetwork</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.10"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">localAddress</span> <span class="o">=</span> <span class="s2">"192.168.100.11"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bindMounts</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/films"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">hostPath</span> <span class="o">=</span> <span class="s2">"/mnt/films"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">tailscale</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># permit caddy to get certs from tailscale</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitCertUid</span> <span class="o">=</span> <span class="s2">"caddy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">jellyfin</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openFirewall</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">caddy</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraConfig</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> jellyfin.tailnet-name.ts.net {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> reverse_proxy localhost:8096
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1">
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># open https port</span>
+</span></span><span class="line"><span class="cl"> <span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">system</span><span class="o">.</span><span class="n">stateVersion</span> <span class="o">=</span> <span class="s2">"23.05"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="err">}</span>
+</span></span></code></pre></div><p>This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.</p>
+<p>Once you’ve logged into the container <code>sudo nixos-container root-login jellyfin</code> and authenticated with tailscale <code>sudo tailscale up</code>, you should be able to access your jellyfin in your browser at <code>https://jellyfin.tailnet-name.ts.net</code>.</p>
+<p>As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to <a href="https://tailscale.com/kb/1084/sharing/">share</a> a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.</p>
+
+
+
+
+
+ -
+
learning about qtile widgets via the medium of cricket
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ Mon, 03 Apr 2023 00:00:00 +0000
+
+ http://localhost:1313/learning-about-qtile-widgets-via-the-medium-of-cricket/
+ <p>I’m a person who has spent an unreasonable amount of time making minute changes to the appearance of my bar in qtile. Despite the very nice selection of widgets availabe by default with qtile, it was only a matter of time before I decided I wanted to experiment with making my own custom widget. Fortunately, if you can do a bit of python this is quite an approachable undertaking.</p>
+<p>The dream widget I was lacking was a little live crikcet score ticker type thing; something which would scroll along on my bar showing me the score in live cricket matches. I’m sure this will interest very few people but I learnt some good stuff along the way.</p>
+<h3 id="hello-world">Hello World?!</h3>
+<p>As far as I can tell from looking at the code for some of the <a href="https://github.com/qtile/qtile/tree/master/libqtile/widget">built-in widgets</a> and <a href="https://docs.qtile.org/en/latest/manual/howto/widget.html">this very helpful guide</a>, a basic hello world widget would look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HelloWorld</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">_TextBox</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s1">'Hello world!'</span>
+</span></span></code></pre></div><p>Qtile provides a selection of base widget classes to do various useful things. This example uses the simple <code>_TextBox</code> which displays the content of the <code>self.text</code> property.</p>
+<h3 id="hello-world-version-2">Hello World Version 2</h3>
+<p>Very nice, but for the cricket widget we’ll need something which lets us update the text. The answer is <code>ThreadPoolText</code>. This class lets you periodically update the text by overridding its <code>poll</code> method with a function that returns the updated text.</p>
+<p>This example updates itself with hello world in a different language every five seconds.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">HolaMundo</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">"Update interval for the widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">HolaMundo</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Hola mundo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Ciao mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'مرحبا بالعالم'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Saluton Mondo'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'Sawubona Mhlaba'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">messages</span><span class="p">)</span>
+</span></span></code></pre></div><p>Along with the whole poll thing, this example also introduces <code>defaults</code>. This is a list of tuples which define parameters that the user can configure. Here we’ve added <code>update_interval</code> which defines how often the widget is updated.</p>
+<h3 id="cricket-scores">Cricket Scores</h3>
+<p>For getting the cricket scores we’ll be using a handy rss feed from cricinfo so no brute force scraping will be required, just my beloved <a href="https://pypi.org/project/feedparser/">feedparser</a>. This doesn’t involve anything directly widget related, just massaging the rss feed into something that would look useful on your bar. Anyway, this is what the finished item looked like.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.widget</span> <span class="kn">import</span> <span class="n">base</span>
+</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">feedparser</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">CricketScores</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">ThreadPoolText</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"update_interval"</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="s2">"Update interval for the cricket scores widget"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"teams"</span><span class="p">,[],</span><span class="s2">"Teams to display scores for"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"separator"</span><span class="p">,</span><span class="s2">" </span><span class="se">\U0001F3CF</span><span class="s2"> "</span><span class="p">,</span><span class="s2">"Text to place between scores"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="s2">"no_scores_string"</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">"Text to show when there are no scores to show"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="bp">self</span><span class="o">.</span><span class="n">add_defaults</span><span class="p">(</span><span class="n">CricketScores</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_scores</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># parse rss feed and get </span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># live matches from title field</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://static.cricinfo.com/rss/livescores.xml"</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="n">feed</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># filter live matches</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="s2">"*"</span> <span class="ow">in</span> <span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">match</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># remove scores not involving chosen teams</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">team</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">teams</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">team</span> <span class="ow">in</span> <span class="n">score</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">filtered_scores</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1"># if no scores, show no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filtered_scores</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_scores_string</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># form pretty string with separators</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">=</span> <span class="s2">""</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">score</span> <span class="ow">in</span> <span class="n">filtered_scores</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">score</span> <span class="o">!=</span> <span class="n">filtered_scores</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">separator</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">final_scores</span> <span class="o">+=</span> <span class="n">score</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">final_scores</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">get_scores</span><span class="p">()</span>
+</span></span></code></pre></div><h3 id="actaully-using-it-in-your-config">Actaully Using It In Your Config</h3>
+<p>Assuming you have a <code>my_widget.py</code> file in the same directory as your <code>config.py</code>, you simply have to import it and add it your list of widgets.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">my_widget</span> <span class="kn">import</span> <span class="n">LovelyWidget</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">LovelyWidget</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widget</span><span class="o">.</span><span class="n">GroupBox</span><span class="p">(),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Happy widget writing.</p>
+
+
+
+
+
+ -
+
theming nirvana
+ http://localhost:1313/theming-nirvana/
+ Mon, 13 Mar 2023 00:00:00 +0000
+
+ http://localhost:1313/theming-nirvana/
+ <p>As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered <a href="https://github.com/nix-community/home-manager">home-manager</a> and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.</p>
+<p><a href="https://sr.ht/~misterio/nix-colors/">Nix-colors</a> lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!</p>
+<h3 id="how-to-make-it-work">how to make it work</h3>
+<p>This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of <a href="https://sr.ht/~misterio/nix-colors/#setup">this</a>.</p>
+<p>First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my <code>flake.nix</code> look something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="s2">"github:misterio77/nix-colors"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">homeConfigurations</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"randy@computer"</span> <span class="o">=</span> <span class="n">home-manager</span><span class="o">.</span><span class="n">lib</span><span class="o">.</span><span class="n">homeManagerConfiguration</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraSpecialArgs</span> <span class="o">=</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">nix-colors</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Then you can import the module into your home-manager config, specify a scheme (<a href="https://github.com/tinted-theming/base16-schemes">available schemes here</a>), and get to theming.</p>
+<p>Here’s a simple example where I make my dunst notifications follow the everforest theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">config</span><span class="o">,</span> <span class="n">nix-colors</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">imports</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">nix-colors</span><span class="o">.</span><span class="n">homeManagerModule</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">colorScheme</span> <span class="o">=</span> <span class="n">nix-colors</span><span class="o">.</span><span class="n">colorSchemes</span><span class="o">.</span><span class="n">everforest</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">dunst</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">urgency_normal</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">background</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base01</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">foreground</span> <span class="o">=</span> <span class="s2">"#</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="o">.</span><span class="n">base05</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><h3 id="a-couple-of-additional-tips-and-tricks">a couple of additional tips and tricks</h3>
+<p>First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span> <span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="n">inputs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="k">inherit</span> <span class="p">(</span><span class="n">inputs</span><span class="o">.</span><span class="n">nix-colors</span><span class="o">.</span><span class="n">lib-contrib</span> <span class="p">{</span> <span class="k">inherit</span> <span class="n">pkgs</span><span class="p">;</span> <span class="p">})</span> <span class="n">gtkThemeFromScheme</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="k">in</span> <span class="k">rec</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">gtk</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">theme</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">package</span> <span class="o">=</span> <span class="n">gtkThemeFromScheme</span> <span class="p">{</span> <span class="n">scheme</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="p">;</span> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">services</span><span class="o">.</span><span class="n">xsettingsd</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/ThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">theme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"Net/IconThemeName"</span> <span class="o">=</span> <span class="s2">"</span><span class="si">${</span><span class="n">gtk</span><span class="o">.</span><span class="n">iconTheme</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with <code>home.file</code>. I do this for qtile.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">config</span><span class="o">,</span> <span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">c</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">colorScheme</span><span class="o">.</span><span class="n">colors</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"><span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">home</span><span class="o">.</span><span class="n">file</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">".config/qtile/colors.py"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">text</span> <span class="o">=</span> <span class="s1">''
+</span></span></span><span class="line"><span class="cl"><span class="s1"> scheme = {
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'yellow': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0A</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'orange': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base09</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'red': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0F</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'magenta': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base08</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'violet': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0E</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'blue': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0D</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'cyan': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0C</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> 'green': "#</span><span class="si">${</span><span class="n">c</span><span class="o">.</span><span class="n">base0B</span><span class="si">}</span><span class="s1">",
+</span></span></span><span class="line"><span class="cl"><span class="s1"> }
+</span></span></span><span class="line"><span class="cl"><span class="s1"> ''</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">}</span>
+</span></span></code></pre></div><p>You can then import the colors into your <code>config.py</code> and use them as you see fit.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">colors</span> <span class="kn">import</span> <span class="n">scheme</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">layouts</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">layout</span><span class="o">.</span><span class="n">MonadTall</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_normal</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'yellow'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="n">border_focus</span> <span class="o">=</span> <span class="n">scheme</span><span class="p">[</span><span class="s1">'green'</span><span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>That’s it for today. Thank you to the <a href="https://github.com/Misterio77">hero</a> that made this.</p>
+
+
+
+
+
+ -
+
translating docker to nix?!
+ http://localhost:1313/translating-docker-to-nix/
+ Tue, 28 Feb 2023 00:00:00 +0000
+
+ http://localhost:1313/translating-docker-to-nix/
+ <p>In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.</p>
+<h3 id="nix---docker-compose---docker-run">nix -> docker compose -> docker run</h3>
+<p>To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my <a href="https://docs.searxng.org/">searxng</a> instance.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"searxng"</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">autoStart</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">image</span> <span class="o">=</span> <span class="s2">"searxng/searxng"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">volumes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"/srv/searx:/etc/searxng"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">environment</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">BASE_URL</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">INSTANCE_NAME</span> <span class="o">=</span> <span class="s2">"go on big boy dont be shy"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"8080:8080"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Here is the same thing written in a <code>docker-compose.yml</code> style format.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">searxng</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">searxng/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">/srv/searxng:/etc/searxng</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">environment</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">BASE_URL=https://searx.jdysmcl.xyz/;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">INSTANCE_NAME=go on big boy dont be shy;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">ports</span><span class="p">:</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="s2">"8080:8080"</span><span class="w">
+</span></span></span></code></pre></div><p>Also, this is what it would look like as a simple old <code>docker run</code>.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">$ docker pull searxng/searxng
+</span></span><span class="line"><span class="cl">$ docker run --rm <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -d -p 8080:8080 <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -v <span class="s2">"/srv/searxng:/etc/searxng"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"BASE_URL=http://searx.jdysmcl.xyz/"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> -e <span class="s2">"INSTANCE_NAME=go on big boy dont be shy"</span> <span class="se">\
+</span></span></span><span class="line"><span class="cl"><span class="se"></span> searxng/searxng
+</span></span></code></pre></div><h3 id="bits-and-bobs">bits and bobs</h3>
+<p>As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in <a href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/oci-containers.nix">oci-containers.nix</a>. As far as I can tell, your best bet in these scenarios is <code>virtualisation.oci-containers.containers.<name>.extraOptions</code>; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">virtualisation</span><span class="o">.</span><span class="n">oci-containers</span><span class="o">.</span><span class="n">containers</span><span class="o">.</span><span class="s2">"vpn"</span><span class="o">.</span><span class="n">extraOptions</span> <span class="err">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--cap-add=net_admin"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--device=/dev/net/tun"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"--network=bridge"</span>
+</span></span><span class="line"><span class="cl"><span class="p">];</span>
+</span></span></code></pre></div><p>With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.</p>
+<p>One final note: nix provides the option to choose between docker and podman with <code>virtualisation.oci-containers.containers.backend</code>. This defaults to podman.</p>
+
+
+
+
+
+ -
+
simple nixos config for vps static site
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ Sun, 29 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/simple-nixos-config-for-vps-static-site/
+ <p>Setting up a little static site is something I’ve done a few different times on a few different operating systems. It’s a slightly fiddly task with a few disparate jobs that all need looking after: ssh, let’s encrypt, nginx. In my opinion, it is one of the moments where consolidating all the little bits and bobs you need to setup into one common configuration is very useful.</p>
+<p>I’m going to go through a bit of the nixos config I’ve got for my vps.</p>
+<h3 id="ssh">SSH</h3>
+<p>Having a way to to get into your server is useful. Managing ssh on nix is very simple; this enables the ssh daemon, tells it what port to run on, disables plain text passwords, and disables root login.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">openssh</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ports</span> <span class="o">=</span> <span class="p">[</span> <span class="mi">69</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">passwordAuthentication</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">permitRootLogin</span> <span class="o">=</span> <span class="s2">"no"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="adding-a-user">ADDING A USER</h3>
+<p>Generally, it’s nice to have a user so you’re not just rawdogging everything as root. This adds a user called ronald, sets their default shell, and adds them to some useful groups. You can even add your public ssh keys here for ultimate convenience.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">users</span><span class="o">.</span><span class="n">users</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ronald</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">isNormalUser</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">shell</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">fish</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extraGroups</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"wheel"</span> <span class="s2">"nginx"</span> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="n">openssh</span><span class="o">.</span><span class="n">authorizedKeys</span><span class="o">.</span><span class="n">keyFiles</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"/path/to/public/key/file"</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="nginx">NGINX</h3>
+<p>I use nginx to serve my sites. Compared to the nginx config I used to mess around with, the equivalent nix config is very clean. This chunk tells nginx to serve the contents of <code>/var/www/example-site</code> at <code>example-site.here</code>. It also opens the ports for http and https in the firewall.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">nginx</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">virtualHosts</span><span class="o">.</span><span class="s2">"example-site.here"</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enableACME</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">forceSSL</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">root</span> <span class="o">=</span> <span class="s2">"/var/www/example-site/"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="n">networking</span><span class="o">.</span><span class="n">firewall</span><span class="o">.</span><span class="n">allowedTCPPorts</span> <span class="err">=</span> <span class="p">[</span> <span class="mi">80</span> <span class="mi">443</span> <span class="p">];</span>
+</span></span></code></pre></div><h3 id="https">HTTPS</h3>
+<p>You can also make nix deal with all the let’s encrypt certbot stuff. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">security</span><span class="o">.</span><span class="n">acme</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">acceptTerms</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">defaults</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="s2">"ronald@email.yes"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This will set up certificates for any sites you set the <code>enableAMCE</code> to true option for.</p>
+<h3 id="cron">CRON</h3>
+<p>This is one final little tidbit I set up the other day. I had got bored of having to ssh into my server to manually copy my updated site to the website root. The problem was I would need root privileges on the server to rsync the files to the website root. This seemed like a whole minefield I didn’t want to mess with. Instead I set up a little cron job which copies a directory from my home to the website root every hour.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">services</span><span class="o">.</span><span class="n">cron</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">systemCronJobs</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"@hourly root cp -r /home/ronald/example-site /var/www/"</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>This means I can just rsync the updated site from my laptop to the server and it’ll be updated within the hour. Good enough for me.</p>
+
+
+
+
+
+ -
+
podcast setup for broke boys whose trash phone cant hack modern apps
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ Tue, 24 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/podcast-setup-for-broke-boys-whose-trash-phone-cant-hack-modern-apps/
+ <p>I have an old sad android phone with 2GB of ram which nowadays seems to struggle with anything but the most lightweight apps. As a result of this I have been ‘podcast-player-hopping’ without success for the last couple of months trying to find something which doesn’t nuke my phone whenever I use it. In a moment of desperation it occured to me that a creative solution might be required. The gameplan was this:</p>
+<ul>
+<li>write python script to download podcasts</li>
+<li>set up cron job on my server to run script every couple of hours</li>
+<li>sync podcasts across my devices using the lovely <a href="https://syncthing.net/">syncthing</a></li>
+<li>listen to podcasts using vlc which my phone loves</li>
+</ul>
+<p>For the python script I used the lovely <a href="https://feedparser.readthedocs.io/en/latest/introduction.html">feedparser</a> module for easy talking to my rss feeds.</p>
+<h3 id="where-the-podcasts-go">WHERE THE PODCASTS GO</h3>
+<p>First thing I would want my script to do is create a subdirectory of my main podcast directory for each individual podcast. After plopping all my feeds in a list like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">rss_urls</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://anchor.fm/s/1311c8b8/podcast/rss'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://feeds.acast.com/public/shows/5e7b777ba085cbe7192b0607'</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>I wrote a little function that would parse each of these feeds get its name, and make a directory if one does not already exist.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_dirs</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="s1">'feed'</span><span class="p">][</span><span class="s1">'title'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">current_feeds</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">feed_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">current_feeds</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">feed_name</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="downloading">DOWNLOADING</h3>
+<p>With this sorted I now turned to the actual downloading of podcasts. This function parses each rss feed, filters it for entries from the last week, then grabs a title and a url for the audio file. These are stuck together into a list of lists with each list representing a separate entry.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pods</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">global</span> <span class="n">feed_info</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">rss_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">feedparser</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">pod</span><span class="o">.</span><span class="n">published_parsed</span><span class="p">)</span> <span class="o"><</span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="mi">7</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">feed</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">title</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span> <span class="o">=</span> <span class="n">pod</span><span class="o">.</span><span class="n">enclosures</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">href</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_info</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_name</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pod_dl</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">feed_info</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pod_info</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">feed_info</span>
+</span></span></code></pre></div><p>This next function looks at all the podcast subdirectories and returns a list of all the podcasts I already have downloaded. This can be used when downloading to only get new podcasts.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_downloads</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">downloads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">downloads</span>
+</span></span></code></pre></div><p>Now for the actual getting of the audio files. Here we use requests to make a request to the audio file url and write the content to the relevant directory. I also append a .mp3 to the filenames so they play nice with media players.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">download</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">a</span> <span class="o">=</span> <span class="n">get_pods</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">b</span> <span class="o">=</span> <span class="n">get_downloads</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="s1">'.mp3'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">b</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">dl</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">pod</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'Download Error'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.mp3'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">dl</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
+</span></span></code></pre></div><h3 id="pruning">PRUNING</h3>
+<p>As it stands, the script does downloading great. The only thing we need is some kind of automatic deletion so my phone doesnt get clogged up with old podcasts. This function checks for files which were created over a week ago and deletes the offenders.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">trim</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pods</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pod</span> <span class="ow">in</span> <span class="n">pods</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">st</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="n">mtime</span><span class="o">=</span><span class="n">st</span><span class="o">.</span><span class="n">st_mtime</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">mtime</span> <span class="o">></span> <span class="p">(</span><span class="mi">86400</span><span class="o">*</span><span class="n">trim_age</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pod_dir</span> <span class="o">+</span> <span class="nb">dir</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="n">pod</span><span class="p">)</span>
+</span></span></code></pre></div><p>The last thing is to call the functions:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">create_dirs</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">download</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"><span class="n">trim</span><span class="p">()</span>
+</span></span></code></pre></div><p>Of course this slightly ramshackle approach is certainly not for everyone lol but as it stands it’s working quite nicely for me. Lots of love and happy listening :)</p>
+
+
+
+
+
+ -
+
elite bread dough for lazy boys
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ Sun, 22 Jan 2023 00:00:00 +0000
+
+ http://localhost:1313/elite-bread-dough-for-lazy-boys/
+ <h3 id="ingredienti">INGREDIENTI</h3>
+<ul>
+<li>flour (ideally bread flour but if you don’t have it, it’s not the end of the world)</li>
+<li>water</li>
+<li>salt</li>
+<li>yeast (i use the little dried packet stuff)</li>
+</ul>
+<h3 id="ratios">RATIOS</h3>
+<p>To start measure the weight of flour; this is what we’ll work from. You can now work out how much of the other ingredients you need using these ratios:</p>
+<ul>
+<li>65% water</li>
+<li>2% salt</li>
+<li>0.5% yeast (this amount doesn’t particularly matter, as long as it’s in this ballpark)</li>
+</ul>
+<p>So if we used 1kg of flour for example, the recipe would look like this:</p>
+<ul>
+<li>1000g flour</li>
+<li>650g water</li>
+<li>20g salt</li>
+<li>5g yeast</li>
+</ul>
+<h3 id="steps">STEPS</h3>
+<ol>
+<li>Put all the ingredients in a bowl nad mix until the flour is hydrated (you do not need to knead it, just bring it together).</li>
+<li>Put in the fridge to slowly proof for at least a day.</li>
+<li>Remove dough as required from the fridge and place in desired baking vessel (you don’t have to bake it all at once, I sometimes make a big batch and bake multiple things over the cours of a few days).</li>
+<li>Proof in vessel for an additional hour or so at room temperature.</li>
+<li>Bake!</li>
+</ol>
+<h3 id="some-helpful-resources">SOME HELPFUL RESOURCES</h3>
+<ul>
+<li><a href="https://cooking.nytimes.com/recipes/11376-no-knead-bread">Jim Lahey no knead bread</a></li>
+<li><a href="https://www.youtube.com/watch?v=uWbl3Sr2y1Y">Kenji video</a></li>
+<li><a href="https://www.youtube.com/watch?v=o4ABOKdHEUs">Ragusea pizza video</a></li>
+</ul>
+
+
+
+
+
+ -
+
multi user qtile fiddling
+ http://localhost:1313/multi-user-qtile-fiddling/
+ Tue, 20 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/multi-user-qtile-fiddling/
+ <p>This post is going to detail how I solved a very particular problem I had created for myself. First, a quick description of the problem. I use home-manager on nixos to declaratively configure what happens on my computer. In the cases where home-manager does not expose sufficient configuration options for my liking (qtile for example), I instead link a configuration file from my nixos config to where it belongs in my home using <code>xdg.configFile</code>. This is what I do with my qtile <code>config.py</code>. I use qtile on my desktop and laptop but I dont want an identical setup on the two machines. I have jumped through many different slightly silly hoops in my nixos config sort of solving this problem until the other day it occured to me this could all be achieved with my python in my qtile config.</p>
+<h3 id="the-nub-of-the-problem">THE NUB OF THE PROBLEM</h3>
+<p>I basically just want the config to work out which computer it’’s on and then change some things accordingly. This can be achieved by getting the hostname with the socket module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'baron'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my desktop</span>
+</span></span><span class="line"><span class="cl"><span class="k">elif</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'countess'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># some stuff i want to happen on my laptop </span>
+</span></span></code></pre></div><p>There are three main things that I like to differ between my two computers:</p>
+<ul>
+<li>widgets on my bar (I don’t need brightness and battery on my desktop)</li>
+<li>keybindings</li>
+<li>programs to autostart</li>
+</ul>
+<h3 id="widgets">WIDGETS</h3>
+<p>My current solution for this is to define to separate lists of widgets and then point to each one when I make my bar for each computer. This isn’t perfect; it would be nice to have a list of all common widgets and then add to that with the unique ones. I haven’t worked out a way to add the additional widgets without just plopping them all at the end of the bar which isn’t necessarily where I want them (thinking about this now I think I might be able to use the insert method with a little for loop).</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_widgets</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># all the great widgets i want on my laptop</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">screens</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Screen</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">top</span> <span class="o">=</span> <span class="n">bar</span><span class="o">.</span><span class="n">Bar</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">widgets</span> <span class="o">=</span> <span class="n">countess_widgets</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><h3 id="keybindings">KEYBINDINGS</h3>
+<p>For keybindings I use extend to add some additional bindings to my global ones. This is mainly useful for the ones I use to change brightness on my laptop.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">countess_keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Up'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -A 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight up'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'Down'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'light -U 5'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'backlight down'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">keys</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">countess_keys</span><span class="p">)</span>
+</span></span></code></pre></div><p>You could even change a specific global binding on one computer if you knew its index in the list:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span><span class="p">[</span><span class="mi">420</span><span class="p">]</span> <span class="o">=</span> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">],</span> <span class="s1">'d'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">spawn</span><span class="p">(</span><span class="s1">'dmenu_run'</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span> <span class="o">=</span> <span class="s1">'dmenu'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="autostart">AUTOSTART</h3>
+<p>Finally, I use this to autostart different programs which I want to change on each computer. For example I use an xrandr command to make sure my desktop monitor is at 144hz. It looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nd">@hook.subscribe.startup_once</span>
+</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">autostart</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">processes</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'feh'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--bg-scale'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'/home/james/pics/wallpapers/beaut.jpg'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">],</span>
+</span></span><span class="line"><span class="cl"> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'xrandr'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--output'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'DisplayPort2'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--primary'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--mode'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'1920x1080'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'--rate'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'143.85'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">processes</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
+</span></span></code></pre></div><p>Of course, there are many ways that this could all be achievd but I think it’s quite neat having it all in my one qtile config. That’s about it for today. lots of love x</p>
+
+
+
+
+
+ -
+
teeny tiny bash fetch script
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ Sat, 10 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/teeny-tiny-bash-fetch-script/
+ <p>This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -A <span class="nv">fetch</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>user<span class="o">]=</span><span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>host<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /etc/hostname<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>uptime<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>uptime <span class="p">|</span> awk <span class="s1">'{print $3}'</span> <span class="p">|</span> sed <span class="s1">'s/:/h / ; s/,/m/'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>kernel<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>awk <span class="s1">'{print $3}'</span> /proc/version<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>distro<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n <span class="s1">'s/^PRETTY_NAME="//p'</span> /etc/os-release <span class="p">|</span> sed <span class="s1">'s/"//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>shell<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>basename <span class="nv">$SHELL</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>de<span class="o">]=</span><span class="s2">"</span><span class="nv">$XDG_CURRENT_DESKTOP</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>terminal<span class="o">]=</span><span class="s2">"</span><span class="nv">$TERM</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>editor<span class="o">]=</span><span class="s2">"</span><span class="nv">$EDITOR</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>root<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $6}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>df -Th / <span class="p">|</span> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ip<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>host myip.opendns.com resolver1.opendns.com <span class="p">|</span>
+</span></span><span class="line"><span class="cl"> tail -n <span class="m">1</span> <span class="p">|</span> awk <span class="s1">'{print $4}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>battery<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>cat /sys/class/power_supply/BAT0/capacity<span class="k">)</span><span class="s2">%"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>cpu<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>sed -n 5p /proc/cpuinfo <span class="p">|</span> cut -d: -f2<span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>ram<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 2p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>swap<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $3}'</span><span class="k">)</span><span class="s2"> /
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>free -h <span class="p">|</span> sed -n 3p <span class="p">|</span> awk <span class="s1">'{print $2}'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"> <span class="o">[</span>display<span class="o">]=</span><span class="s2">"</span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $1}'</span><span class="k">)</span><span class="s2">,
+</span></span></span><span class="line"><span class="cl"><span class="s2"> </span><span class="k">$(</span>xrandr <span class="p">|</span> grep <span class="s1">'*'</span> <span class="p">|</span> awk <span class="s1">'{print $2}'</span> <span class="p">|</span> sed <span class="s1">'s/*/Hz/ ; s/+//'</span><span class="k">)</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).</p>
+<p>Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">colors</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;30m"</span> <span class="c1"># black</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;31m"</span> <span class="c1"># red</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;32m"</span> <span class="c1"># green</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;33m"</span> <span class="c1"># blue</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;34m"</span> <span class="c1"># yellow</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;35m"</span> <span class="c1"># pink</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;36m"</span> <span class="c1"># magenta</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"\e[0;1;37m"</span> <span class="c1"># white</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span></code></pre></div><p>I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">pre</span><span class="o">=</span><span class="s2">"->"</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">random_color <span class="o">()</span> <span class="o">{</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">size</span><span class="o">=</span><span class="si">${#</span><span class="nv">colors</span><span class="p">[@]</span><span class="si">}</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">index</span><span class="o">=</span><span class="k">$((</span><span class="nv">$RANDOM</span> <span class="o">%</span> <span class="nv">$size</span><span class="k">))</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"</span><span class="si">${</span><span class="nv">colors</span><span class="p">[</span><span class="nv">$index</span><span class="p">]</span><span class="si">}${</span><span class="nv">pre</span><span class="si">}</span><span class="s2">\e[0m"</span>
+</span></span><span class="line"><span class="cl"><span class="o">}</span>
+</span></span></code></pre></div><p>My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">declare</span> -a <span class="nv">order</span><span class="o">=(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"user"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"host"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"uptime"</span> <span class="c1"># uses uptime command</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"kernel"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"distro"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"shell"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"de"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"terminal"</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"editor"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ip" # uses host command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "cpu"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "ram" # uses free command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "swap" # uses free also</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "root" # uses df command</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "battery"</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># "display" # uses xrandr</span>
+</span></span><span class="line"><span class="cl"><span class="o">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="k">for</span> info in <span class="s2">"</span><span class="si">${</span><span class="nv">order</span><span class="p">[@]</span><span class="si">}</span><span class="s2">"</span><span class="p">;</span> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> -e <span class="s2">"</span><span class="k">$(</span>random_color<span class="k">)</span><span class="s2"> \e[0;1;3m</span><span class="nv">$info</span><span class="s2">\e[0m</span><span class="si">${</span><span class="nv">sep</span><span class="si">}${</span><span class="nv">fetch</span><span class="p">[</span><span class="nv">$info</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
+</span></span><span class="line"><span class="cl"><span class="k">done</span>
+</span></span></code></pre></div><p>This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety <a href="https://gitlab.com/robbygozzarder/golazo">here</a>. This is a pretty picture of a few variations.</p>
+<p><img src="http://localhost:1313/image/golazo.png" alt="golazo"></p>
+
+
+
+
+
+ -
+
get the thoughts out of your head and into a digital format with this python journal script
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ Thu, 01 Dec 2022 00:00:00 +0000
+
+ http://localhost:1313/get-the-thoughts-out-of-your-head-and-into-a-digital-format-with-this-python-journal-script/
+ <p>Since getting going with emacs I’ve gone down the org-mode rabbit hole a little bit. In particular the very nice <a href="https://github.com/bastibe/org-journal">org-journal</a> package. It basically does what it says on the tin: maintains a journal with a selection of org files. This has been very nice for me. I have often thought about journalling but never really got up a head of steam. Somehow having an entry a keybinding away while I’m doing something with my text editor makes it a lot more palletable.</p>
+<p>Having said all this, I am not completely converted to the church of emacs. Thus, I thoght it would be nice to write a little editor agnostic script which would emulate some of org-journal’s features but allow you to use whatever editor you like with markdown.</p>
+<h3 id="whats-the-time">WHAT’S THE TIME?</h3>
+<p>First things first, I wrote this little function that would give you a formatted version of your local time. This will be important as a lot of this comes down to dates and times really. It uses python’s time module:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">whats_the_time</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()))</span>
+</span></span></code></pre></div><p>This function takes a string using <a href="https://www.w3schools.com/python/gloss_python_date_format_codes.asp">python date format codes</a> and spits out the corresponding time. For example, <code>'%A %d %B, %Y'</code> would give you Wednesday 12 December, 2022.</p>
+<h3 id="what-to-call-the-files">WHAT TO CALL THE FILES?</h3>
+<p>My plan is to have three options for <code>journal_frequency</code>: daily, monthly, and yearly. Depending on the value of this variable, each journal file the script creates will represent a day, month, or year. This function gives you a different filename depending on the <code>journal_frequency</code> that is set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_filename</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'daily'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m</span><span class="si">%d</span><span class="s1">'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'monthly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y%m'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">journal_frequency</span> <span class="o">==</span> <span class="s1">'yearly'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.md'</span>
+</span></span></code></pre></div><h3 id="do-we-need-a-new-file">DO WE NEED A NEW FILE?</h3>
+<p>As I could see it, the next problem was determining whether a new journal file was needed. This would only happen if it was the first entry for a day, month, or year. Otherwise, you would simply want to add to the existing file. I came up with this little function using the os module to check if the file that would be created already exists:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">False</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="kc">True</span>
+</span></span></code></pre></div><p>MAKING FILES AND PUTTING THINGS IN THEM</p>
+<p>Now we have that admin out the way, we’re on the home straight. This function creates a file and adds a little title heading at the top using the <code>title_string</code> variable. This will be called when we do need a new file:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_file</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'# '</span> <span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">title_string</span><span class="p">))</span>
+</span></span></code></pre></div><p>This guy adds a subheading wtih the current time as default using the <code>entry_string</code> variable. If you had <code>journal_frequency</code> set to monthly or yearly though you would likely want to edit this to include bits fo the date. This is called evry time you run the script.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_date</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span><span class="n">make_filename</span><span class="p">())</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="s1">'### '</span><span class="o">+</span> <span class="n">whats_the_time</span><span class="p">(</span><span class="n">entry_string</span><span class="p">))</span>
+</span></span></code></pre></div><h3 id="opening-a-text-editor">OPENING A TEXT EDITOR</h3>
+<p>Final order of business: how to open the appropriate journal file with the user’s chosen editor. For this we can use the subprocess module and <a href="https://docs.python.org/3/library/subprocess.html#popen-constructor">Popen</a>. By default I have this set to get your EDITOR environemnt variable and use that (come to think of it that probs won’t work with tui programs) but it could be set to anything.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">open_editor</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">cmd</span> <span class="o">=</span> <span class="p">[</span> <span class="n">editor</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">journal_dir</span><span class="p">,</span> <span class="n">make_filename</span><span class="p">())</span> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">process</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now it’s just a matter of sticking all the functions together:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">new_file_required</span><span class="p">():</span>
+</span></span><span class="line"><span class="cl"> <span class="n">create_file</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">write_date</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">open_editor</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">main</span><span class="p">()</span>
+</span></span></code></pre></div><p>As simple as it is, it works reasonalby well as it stands. I would though like to add the ability to customise the file format you want to use so you could have org, plain text, markdown, or whatever. I’ve got the script set to just run with a keybinding at the moment so it fulfils the immediacy I was enjoying with org-journal. You can find the script <a href="https://gitlab.com/robbygozzarder/py">here</a> atm. BYEBYE xxx</p>
+
+
+
+
+
+ -
+
lowkey emacs setup
+ http://localhost:1313/lowkey-emacs-setup/
+ Fri, 18 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/lowkey-emacs-setup/
+ <p>About a month ago I was a little bored and thought I’d give emacs a go. There’s something fun about trying out these mythical pieces of software that have been around forever; kind of like watching The Godfather for the first time. Like many extensible, super configurable programs, emacs seems kind of impenetrable at first glance. I tried doing the tutorial but kind of glazed over after a while with the endless stream of C-a C-b C-c. There’s also the quite jarring default theme which wasn’t vibing with the lovely screenshots I had seen on the internet. Anyway, after quite a bit of fiddling I’ve landed on a simple little setup that I’ve been quite enjoying. Here are a few little pointers to hopefully ease you in.</p>
+<h3 id="aesthetic-niceties">AESTHETIC NICETIES</h3>
+<p>First things first, assuming you’re on linux emacs is configured with a file at <code>~/.emacs.d/init.el</code>. As a terrible aesthete, the first thing I was worried about was changing the theme. This can be achieved with <code>M-x load-theme</code>; if you want the setting to persist though you can add this to you init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'misterioso</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>There are a few themes out of the box but if you’re looking for some more I would recomment the doom-themes package. Speaking of packages, emacs has a built in package-manager that installs packages from the Emacs Lisp Package Archive (GNU ELPA); I unfortunately know very little about this as I’ve been using nix to manage my emacs packages.</p>
+<p>Anyway we’ve got a theme, how about a custom startup message for our initial buffer:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">inhibit-startup-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">inhibit-startup-echo-area-message</span> <span class="no">t</span>
+</span></span><span class="line"><span class="cl"> <span class="nv">initial-scratch-message</span>
+</span></span><span class="line"><span class="cl"> <span class="s">";;oh how i adore to edit text with emacs!"</span><span class="p">)</span>
+</span></span></code></pre></div><p>Maybe you dont want those big old cumbersome toolbars cluttering up your screen:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">scroll-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">tool-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
+</span></span></code></pre></div><p>Perhaps some line highlighting and numbering:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;;line numbering</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">display-line-numbers-type</span> <span class="ss">'relative</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="c1">;;line higlight</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">global-hl-line-mode</span> <span class="no">t</span><span class="p">)</span>
+</span></span></code></pre></div><p>Custom font?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="k">setq</span> <span class="nv">default-frame-alist</span> <span class="o">'</span><span class="p">((</span><span class="nv">font</span> <span class="o">.</span> <span class="s">"agave Nerd Font 14"</span><span class="p">)))</span>
+</span></span></code></pre></div><h3 id="custom-keybindings-and-evil">CUSTOM KEYBINDINGS AND EVIL</h3>
+<p>I don’t know if it’s just sunk cost fallacy or what but having gone to the trouble of learning to some extent how vim works, I kind of feel incomplete without vim keybindings now. Fortunately, emacs has evil mode which effectively emulates vim modal editing in emacs. To configure evil in our init.el we’ll use use-package. This is a macro which - to my understanding - talks to your package manager allowing you to configure installed packages in a nice neat efficient manner. To enable it, add this to your init.el:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nv">eval-when-compile</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nf">require</span> <span class="ss">'use-package</span><span class="p">))</span>
+</span></span></code></pre></div><p>These are the keybindings that I currently have going; nothing too crazy just a few simple things:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">evil</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-mode</span> <span class="mi">1</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">evil-select-search-module</span> <span class="ss">'evil-search-module</span> <span class="ss">'evil-search</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;manage panes</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s"</span><span class="p">)</span> <span class="ss">'evil-window-split</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-v"</span><span class="p">)</span> <span class="ss">'evil-window-vsplit</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-h"</span><span class="p">)</span> <span class="ss">'evil-window-left</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-j"</span><span class="p">)</span> <span class="ss">'evil-window-down</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-k"</span><span class="p">)</span> <span class="ss">'evil-window-up</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-l"</span><span class="p">)</span> <span class="ss">'evil-window-right</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;get files open quick</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-f"</span><span class="p">)</span> <span class="ss">'find-file</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-b"</span><span class="p">)</span> <span class="ss">'dired-jump</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;terminal</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-t"</span><span class="p">)</span> <span class="ss">'ansi-term</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">;;nav buffers</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-,"</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <left>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">define-key</span> <span class="nv">evil-normal-state-map</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-."</span><span class="p">)</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"C-x <right>"</span><span class="p">))</span>
+</span></span><span class="line"><span class="cl"> <span class="p">)</span>
+</span></span></code></pre></div><h3 id="some-friednly-ide-features-you-may-like">SOME FRIEDNLY IDE FEATURES YOU MAY LIKE</h3>
+<p>I don’t know about you but having used vscode here and there I’ve become accustomed to a lot of these little IDE crutches (completion, autopair and the like) and now when I don’t have thme I feel a little sad. Emacs has it covered though as long as you’re happy with installing some additional stuff. Auto-completion? Try company:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="c1">;; enable company in all buffers</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'after-init-hook</span> <span class="ss">'global-company-mode</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">company</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:commands</span> <span class="nv">company-tng-configure-default</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:custom</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; delay to start completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-idle-delay</span> <span class="mi">0</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">;; nb of chars before triggering completion</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">company-minimum-prefix-length</span> <span class="mi">1</span><span class="p">)</span>
+</span></span></code></pre></div><p>You want the nice little autopair brackets?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">flex-autopair</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:config</span>
+</span></span><span class="line"><span class="cl"> <span class="p">(</span><span class="nv">flex-autopair-mode</span> <span class="mi">1</span><span class="p">))</span>
+</span></span></code></pre></div><p>Clever commenting?</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lisp" data-lang="lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nf">use-package</span> <span class="nv">smart-comment</span>
+</span></span><span class="line"><span class="cl"> <span class="ss">:bind</span> <span class="p">(</span><span class="s">"M-c"</span> <span class="o">.</span> <span class="nv">smart-comment</span><span class="p">))</span>
+</span></span></code></pre></div><p>Here’s a little pic of the current setup :)</p>
+<p><img src="http://localhost:1313/image/emacs.png" alt="emacs"></p>
+
+
+
+
+
+ -
+
setting up a lean mean hugo blogging theme
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ Thu, 10 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/setting-up-a-lean-mean-hugo-blogging-theme/
+ <p>When I first started messing around with hugo, I found the whole thing slihtly mystifying. I downloaded a theme like they asked me, edited the config file to try and customise things a little and quickly broke everything. To be fair, this was mainly due to my tinkering instinct to fly to close to the sun. But anyway, the point at which I started to really appreciate the power of hugo was when I tried to make my own - admittedly less feautureful - theme. This selection of tips and tricks will assume that you’ve just run something like <code>hugo new site lovely-new-website</code>, entered the new directory with <code>cd lovely-new-website</code> and you’ve got a selection of mostly empty directories looking something like this.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">├── archetypes
+</span></span><span class="line"><span class="cl">│ └── default.md
+</span></span><span class="line"><span class="cl">├── config.toml
+</span></span><span class="line"><span class="cl">├── content
+</span></span><span class="line"><span class="cl">├── data
+</span></span><span class="line"><span class="cl">├── layouts
+</span></span><span class="line"><span class="cl">├── public
+</span></span><span class="line"><span class="cl">├── static
+</span></span><span class="line"><span class="cl">└── themes
+</span></span></code></pre></div><p>Our first concern will be getting a barebones theme template that can be customised to our liking. I would recommend <a href="https://github.com/ericmurphyxyz/hugo-starter-theme">this</a> guy which I used to get up and running. You could also check out <a href="https://gitlab.com/robbygozzarder/mcl">my theme</a> which I’m using on this site that is also very simple (as you can probably see from the website lol). Once you’ve got a theme with (I’m using mine as an example) <code>git clone https://gitlab.com/robbygozzarder/mcl</code> and placed it in the themes directory you’ll need to adjust your config.toml file to point it to this theme.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">theme</span><span class="p">=</span><span class="s2">"mcl"</span>
+</span></span></code></pre></div><p>The directory structure of your new theme will look something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">.
+</span></span><span class="line"><span class="cl">└── mcl
+</span></span><span class="line"><span class="cl"> ├── archetypes
+</span></span><span class="line"><span class="cl"> │ └── default.md
+</span></span><span class="line"><span class="cl"> ├── layouts
+</span></span><span class="line"><span class="cl"> │ ├── 404.html
+</span></span><span class="line"><span class="cl"> │ ├── _default
+</span></span><span class="line"><span class="cl"> │ │ ├── list.html
+</span></span><span class="line"><span class="cl"> │ │ └── single.html
+</span></span><span class="line"><span class="cl"> │ ├── index.html
+</span></span><span class="line"><span class="cl"> │ └── partials
+</span></span><span class="line"><span class="cl"> │ ├── footer.html
+</span></span><span class="line"><span class="cl"> │ ├── header.html
+</span></span><span class="line"><span class="cl"> │ └── nav.html
+</span></span><span class="line"><span class="cl"> ├── README.md
+</span></span><span class="line"><span class="cl"> └── static
+</span></span><span class="line"><span class="cl"> └── css
+</span></span><span class="line"><span class="cl"> └── style.css
+</span></span></code></pre></div><p>This is where most of the magic happens:</p>
+<ul>
+<li>The default.md file in the archetypes directory dictates what template to follow when adding new post files.</li>
+<li>The layouts directory is where most of the meat is:
+<ul>
+<li>Firstly, there’s the partials directory which contains outlines for sections which you want to be used multiple times across the site such as a footer (footer.html)</li>
+<li>Sceondly, we have _default which contains outlines for the two types of hugo pages; singles (single.html) such as this individual post page, and lists (list.html) such as the tags and posts pages on this site.</li>
+<li>Partials also contains index.html which (you guessed it!) is your home page.</li>
+</ul>
+</li>
+<li>Last but not least, there’s static which as you can see just has the css for the site (this is all looks though - the action happens in partials).</li>
+</ul>
+<p>Now the theme is sorted the next three things you need to know anything about (imho) are the content, public, and static directories:</p>
+<ul>
+<li>Content is where you put your posts - these are just markdown files which hugo converts to html for you.</li>
+<li>Public is where hugo puts your built - ready to be served - site. You can then copy this directory to wherever your webserver is looking eg. /var/www/jdysmcl</li>
+<li>Static is where assets which you want to use with your site are kept. I basically just use it for images which I can then reference from my posts.</li>
+</ul>
+<p>Now we’ve got the directory what’s happening where admin out the way let’s have a look at what some of the html files in the themes directory look like; this is the index.html for my site for example:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{ partial "header.html" . }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="p"><</span><span class="nt">p</span><span class="p">></span>This is mainly a place for me to document various
+</span></span><span class="line"><span class="cl">bits and bobs I've been doing on my computers.
+</span></span><span class="line"><span class="cl">I am a noob in most things so take anything written
+</span></span><span class="line"><span class="cl">here with a pinch of salt. Lots of love :)<span class="p"></</span><span class="nt">p</span><span class="p">></span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ .Content }}
+</span></span><span class="line"><span class="cl">{{ range .Site.RegularPages | first 5 }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">h3</span><span class="p">></span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"{{ .RelPermalink }}"</span><span class="p">></span>{{ .Title }}<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Summary }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">br</span><span class="p">><</span><span class="nt">br</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ .Date.Format "06 Jan, 2006" }} |
+</span></span><span class="line"><span class="cl"> {{ .WordCount }} words |
+</span></span><span class="line"><span class="cl"> {{ .ReadingTime }} mins |
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> {{ range (.GetTerms "tags") }}
+</span></span><span class="line"><span class="cl"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">'{{ .Permalink }}'</span><span class="p">></span>{{ .LinkTitle }}<span class="p"></</span><span class="nt">a</span><span class="p">></span>
+</span></span><span class="line"><span class="cl"> {{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ end }}
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl">{{ partial "footer.html" . }}
+</span></span></code></pre></div><p>In short, this plops the header and footer partials at the top and bottom of the page respectively, includes a short warning not to listen to me, and then displays my five most recent posts along with a snippet of the post and some accompanyning info: date, word count, reading time, and tags. The keen eyed among you will have noticed that this is a mish mash of normal html tags and strange stuff enclosed in double curly brackets. I’m going to end on this cliffhanger but if you want to know more about the curly brackets check out the hugo docs <a href="https://gohugo.io/templates/introduction">here</a>.</p>
+
+
+
+
+
+ -
+
chess.com api and the continuing search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ Tue, 08 Nov 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-continuing-search-for-en-passant-checkmate/
+ <p>Last time we worked out how to get info for all the games played by titled players in a particular month. Today, we have three objectives:</p>
+<ul>
+<li>Parse this info for the pgn (portable game notation) of each game.</li>
+<li>Write these to a file so we dont have to spend forever downloading them everytime we run the script.</li>
+<li>Devise a way to convert this pgn to a more convenient pythonic format so we can analyse it later.</li>
+</ul>
+<p>First of all, I wrote a little function to get the pgn from the games we downloaded. I added this KeyError exception, but if I’m honest I’m not sure why I was getting this error. Maybe, chess.com doesn’t store pgn for all games? I don’t know.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_pgns</span><span class="p">(</span><span class="n">games</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">game</span> <span class="ow">in</span> <span class="n">games</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgn</span> <span class="o">=</span> <span class="n">game</span><span class="p">[</span><span class="s1">'pgn'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">pgns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s1">'key error um'</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">pgns</span>
+</span></span></code></pre></div><p>Now we have this list of pgns, the next goal is to write them to a file so we theoretically only have to run the stuff from last post once. All the analysis we do on the games can then just be done on the files we save without any talking to the internet required.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">write_pgns</span><span class="p">(</span><span class="n">pgns</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">month</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'/'</span><span class="p">,</span><span class="s1">'_'</span><span class="p">)</span><span class="o">+</span><span class="s1">'.csv'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">pgn</span> <span class="ow">in</span> <span class="n">pgns</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">pgn</span><span class="p">)</span>
+</span></span></code></pre></div><p>Now a pgn looks something like this if it’s just printed as a string:</p>
+<p><img src="http://localhost:1313/image/pgn.webp" alt="image alt text"></p>
+<p>It contains lots of very useful info but for our purposes of finding en passant checkmates, we would ideally just have a list of each move looking something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">moves</span> <span class="o">=</span> <span class="p">[</span> <span class="s1">'e4'</span><span class="p">,</span> <span class="s1">'e5'</span><span class="p">,</span> <span class="s1">'Bc4'</span><span class="p">,</span> <span class="s1">'Nc6'</span><span class="p">,</span> <span class="s1">'Qh5'</span><span class="p">,</span> <span class="s1">'Nf6'</span><span class="p">,</span> <span class="s1">'Qxf7#'</span><span class="p">]</span>
+</span></span></code></pre></div><p>We don’t need the headers, we don’t need the result, and we don’t really need the move numbers (these can be deduced from the list indexes). So the challenge is how to convert the pgn to a list; this is the slightly janky solution I came up wtih.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">get_move_list</span><span class="p">(</span><span class="n">pgn</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="n">pgn</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># start fresh list at move 1 - effectively skipping the headers from the list</span>
+</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="s1">'1.'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1"># gets rid of clock bits and bobs</span>
+</span></span><span class="line"><span class="cl"> <span class="k">elif</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'{'</span> <span class="ow">or</span> <span class="n">item</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'}'</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">pass</span>
+</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">moves</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#remove even indexes from list</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#this gets rid of move numbers and the result of the game</span>
+</span></span><span class="line"><span class="cl"> <span class="k">del</span> <span class="n">moves</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">moves</span>
+</span></span></code></pre></div><p>I don’t doubt it could be done more elegantly but it works I guess. Next time, we’ll deal with working out what a list containing an en passant checkmate would look like.</p>
+
+
+
+
+
+ -
+
chess.com api and the search for en passant checkmate
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ Wed, 26 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/chess.com-api-and-the-search-for-en-passant-checkmate/
+ <p>The chess.com API gives you access to a crazy amount of data on games played on the site. Armed with the knowledge that this data was at my fingertips, I set out to do what any sane person would do: find en passant checkmates. For those not in the know, en passant check mate is kind of the king of moves in chess meme circles. So some sort of python script that identified en passant check mates that occured on the site would be of great value to me.</p>
+<p>First things first, I would need a method of grabbing lots of games from the api. This would be achieved by looking at players on the site and searching their game archives. As I couldn’t think of any obvious way to get completely random players on the site, I used the API’s lists of all titled players (GM, IM, WIM, etc.) on the site. This is what I came up with -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">get_archive_urls</span><span class="p">(</span><span class="n">titled_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">titled_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">title_list</span> <span class="o">=</span> <span class="n">title_list</span><span class="p">[</span><span class="s1">'players'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">players</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">title_list</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">username</span> <span class="ow">in</span> <span class="n">players</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="s1">'https://api.chess.com/pub/player/'</span> <span class="o">+</span> <span class="n">username</span> <span class="o">+</span> <span class="s1">'/games/2022/05'</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_urls</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">archive_urls</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span></code></pre></div><p>This function reads a list of urls, gets a list of all the usernames from the api and then inserts this username into a new url which will allow us to access their games from a particular month. I then returns a list of all of these game archive urls.</p>
+<p>The next order of business is taking this list of urls and turning it into a list of games. It looks quite similar to the previous example -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">grab_games</span><span class="p">(</span><span class="n">archive_urls</span><span class="p">):</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">archive_urls</span><span class="p">:</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
+</span></span><span class="line"><span class="cl"> <span class="n">archive_games</span> <span class="o">=</span> <span class="n">archive</span><span class="p">[</span><span class="s1">'games'</span><span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="n">games</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">archive_games</span><span class="p">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">games</span>
+</span></span></code></pre></div><p>Feeding the first function into the second -></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"> <span class="n">grab_games</span><span class="p">(</span><span class="n">get_archive_urls</span><span class="p">([</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/GM'</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="s1">'https://api.chess.com/pub/titled/WGM'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]))</span>
+</span></span></code></pre></div><p>We get a very long list of json objects (is that the right phrase? um). Each corresponding to one of games played by GMs and WGMs on chess.com during May of 2022. Come back next time to see what we can do with this very long list. Here’s a taster of what the list looks like printed to a terminal - lots of possiblities.</p>
+<p><img src="http://localhost:1313/image/output.webp" alt="image alt text"></p>
+
+
+
+
+
+ -
+
declarative firefox config with home-manager on nixos
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ Sun, 02 Oct 2022 00:00:00 +0000
+
+ http://localhost:1313/declarative-firefox-config-with-home-manager-on-nixos/
+ <p>As a man who finds himself reinstalling his OS more than is probably sensible, any opportunity to minimise the post install admin of sorting out all your settings is an attractive one. With that in mind lets take a look at some of the firefox (my current browser of choice) configuration options avilable to you through home-manager. This assumes you have some sort of home-manager setup working. If you do not I found <a href="https://github.com/misterio77/nix-starter-configs">this</a> friendly githubber’s templates to be very helpful.</p>
+<p>First of all you’ll need to enable firefox with <code>programs.firefox.enable = true;</code></p>
+<h3 id="extensions">EXTENSIONS</h3>
+<p>This will require having the NUR (nix user repo) enabled. But once you do, you can configure any extension you want to be auto installed with something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span><span class="n">pkgs</span><span class="o">,</span> <span class="o">...</span> <span class="p">}:</span>
+</span></span><span class="line"><span class="cl"> <span class="k">let</span>
+</span></span><span class="line"><span class="cl"> <span class="n">addons</span> <span class="o">=</span> <span class="n">pkgs</span><span class="o">.</span><span class="n">nur</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">rycee</span><span class="o">.</span><span class="n">firefox-addons</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="k">in</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">programs</span><span class="o">.</span><span class="n">firefox</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">extensions</span> <span class="o">=</span> <span class="k">with</span> <span class="n">addons</span><span class="p">;</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ublock-origin</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bitwarden</span>
+</span></span><span class="line"><span class="cl"> <span class="n">darkreader</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span></code></pre></div><p>This is the list of <a href="https://nur.nix-community.org/repos/rycee/">all extensions</a> available in the repo.</p>
+<h3 id="bookmarks">BOOKMARKS</h3>
+<p>Bookmarks can be added per profile. The format for it goes something like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">bookmarks</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best website ever!"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">name</span> <span class="o">=</span> <span class="s2">"best OS ever"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="n">url</span> <span class="o">=</span> <span class="s2">"https://nixos.org"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">}</span>
+</span></span><span class="line"><span class="cl"> <span class="p">];</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><h3 id="settings">SETTINGS</h3>
+<p>Again, these can be added per profile. Basically, any option you can find in about:config can be added here; this is a selection of potentially useful options I have set:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="n">profiles</span><span class="o">.</span><span class="n">james</span> <span class="err">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="n">settings</span> <span class="o">=</span> <span class="p">{</span>
+</span></span><span class="line"><span class="cl"> <span class="c1">#newtab stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.startup.homepage"</span> <span class="o">=</span> <span class="s2">"https://searx.jdysmcl.xyz"</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.newtabpage.activity-stream.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some firefox features i don't really want</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.pocket.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"extensions.formautofill.creditCards.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"identity.fxaccounts.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"signon.rememberSignons"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"browser.search.suggest.enabled"</span> <span class="o">=</span> <span class="no">false</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"> <span class="c1">#some privacy stuff</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.resistFingerprinting"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"privacy.trackingprotection.enabled"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"dom.security.https_only_mode"</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
+</span></span><span class="line"><span class="cl"> <span class="p">};</span>
+</span></span><span class="line"><span class="cl"><span class="p">};</span>
+</span></span></code></pre></div><p>Of course I am sure there are many more exciting things that could be done here but this is as far as I have got. For all avilable options you can check out <a href="https://nix-community.github.io/home-manager/options.html">this</a> or alternatively run a <code>man home-configuration.nix</code>. Hope this has been helpful :)</p>
+
+
+
+
+
+ -
+
upgrade your qtile setup with a cute dropdown terminal
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ Fri, 23 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/
+ <p>I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">libqtile.config</span> <span class="kn">import</span> <span class="n">Dropdown</span><span class="p">,</span> <span class="n">Scratchpad</span>
+</span></span><span class="line"><span class="cl">
+</span></span><span class="line"><span class="cl"><span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
+</span></span></code></pre></div><p>I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the <a href="https://docs.qtile.org/en/latest/manual/config/groups.html">qtile docs</a> is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span> <span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">]</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:</p>
+<p><img src="http://localhost:1313/image/dropdown.webp" alt="alt"></p>
+<p>Though this can easily be altered with the x, y, height, and width keys:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">groups</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="n">ScratchPad</span><span class="p">(</span><span class="s2">"scratchpad"</span><span class="p">,</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">DropDown</span><span class="p">(</span>
+</span></span><span class="line"><span class="cl"> <span class="s2">"term"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">kitty</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">opacity</span> <span class="o">=</span> <span class="mf">0.9</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">width</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">height</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="p">])</span>
+</span></span><span class="line"><span class="cl"><span class="p">)</span>
+</span></span></code></pre></div><p>This gives us a little boxy guy in the top left corner:</p>
+<p><img src="http://localhost:1313/image/dropdown2.webp" alt="alt"></p>
+<p>We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">[</span>
+</span></span><span class="line"><span class="cl"> <span class="n">Key</span><span class="p">([</span><span class="n">m</span><span class="p">,</span> <span class="s2">"shift"</span><span class="p">],</span> <span class="s2">"Return"</span><span class="p">,</span>
+</span></span><span class="line"><span class="cl"> <span class="n">lazy</span><span class="o">.</span><span class="n">group</span><span class="p">[</span><span class="s2">"scratchpad"</span><span class="p">]</span><span class="o">.</span><span class="n">dropdown_toggle</span><span class="p">(</span><span class="s2">"terminal"</span><span class="p">),</span>
+</span></span><span class="line"><span class="cl"> <span class="n">desc</span><span class="o">=</span><span class="s1">'dropdown term'</span>
+</span></span><span class="line"><span class="cl"> <span class="p">),</span>
+</span></span><span class="line"><span class="cl"><span class="p">]</span>
+</span></span></code></pre></div><p>Anyway, hope this was useful, happy configurating :)</p>
+
+
+
+
+
+ -
+
rudimentary local scrobbling with bash
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ Tue, 13 Sep 2022 00:00:00 +0000
+
+ http://localhost:1313/rudimentary-local-scrobbling-with-bash/
+ <p>There are lots of music players on linux. I have used lots of them, I quite like some of them. But for some reason I decided I wanted more. With this in mind, over the past few months I have been constructing a sprawling ecosystem of bash scripts all geared towards delivering a customised listening experience tailored perfectly to my every need. In short, the setup uses a simple dmenu file manager to browse my local files and mpv to play them. Today I’ll be talking specifically about my setup for recording the albums I’ve been listening to.</p>
+<h3 id="lets-get-down-to-business">LET’S GET DOWN TO BUSINESS</h3>
+<p>Whenever I select a file to be played with my script I am effectively selecting a path to a file or a path to a directory with files in it which is then fed to mpv. For example, if I’m playing the classic album Lemonade by Beyonce it would look like this:</p>
+<p><code>/home/randy/music/Beyonce/Lemonade/</code></p>
+<p>To append this path to a file called scrobble while removing the first three directories (or the first 18 characters) rather inelegantly:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">printf</span> <span class="s2">"%s"</span> <span class="s2">"</span><span class="nv">$selected_path</span><span class="s2">"</span> <span class="p">|</span> cut -c 18- >> scrobble
+</span></span></code></pre></div><p>As new paths are appended to the file, this will will result in a scrobble file made up of three columns: the first for artists, the second for albums, and the third for songs.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Abdullah Ibrahim/South Africa
+</span></span><span class="line"><span class="cl">Darkside/Psychic
+</span></span><span class="line"><span class="cl">SOPHIE/OIL OF EVERY PEARL<span class="err">'</span>S UN-INSIDES
+</span></span><span class="line"><span class="cl">Nicolas Jaar/Space Is Only Noise/2 Colomb.flac
+</span></span><span class="line"><span class="cl">Townes Van Zandt
+</span></span></code></pre></div><p>As you can see here, unless you only play music song by song, not all columns will always be populated. Now we have a file that contains this information we can do stuff to it. For example, to show our listening history and display it in columns with some pretty labels:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tac scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,track"</span>
+</span></span></code></pre></div><p>Maybe you only want the last ten things you listened to:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tail -n <span class="m">10</span> scrobble <span class="p">|</span> column -t -s <span class="s2">"/"</span> -N <span class="s2">" ,artist,album,song"</span>
+</span></span></code></pre></div><p>To find our most played atrists it’s a little more complicated. We can use awk to extract the artist column and remove all duplicate entries with sort -u to get a list of all played artists to iterate over. Then for each unique artist we grep for instances of them in the artist column and append that number of instances and the artist to a temporary file. This can then displayed as you see fit:</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="k">for</span> album in <span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> scrobble <span class="p">|</span> sort -u<span class="k">)</span>
+</span></span><span class="line"><span class="cl"> <span class="k">do</span>
+</span></span><span class="line"><span class="cl"> <span class="nb">echo</span> <span class="s2">"'</span><span class="nv">$album</span><span class="s2">'/"</span><span class="k">$(</span>awk -F/ <span class="s1">'{ print $2 }'</span> <span class="s2">"</span><span class="nv">$scrob_file</span><span class="s2">"</span> <span class="p">|</span> grep <span class="nv">$album</span> <span class="p">|</span> wc -l<span class="k">)</span><span class="s2">""</span> >> temp
+</span></span><span class="line"><span class="cl"> <span class="k">done</span>
+</span></span></code></pre></div><p>So these are just a few examples; the real point is once you have that file of three columns the world is your oyster. You could probably even use something a little less cumbersome such as python.</p>
+<p>Finally, disclaimer: I am a bash amateur so I hope nothing you’ve seen here was too upsetting. Lots of love x</p>
+
+
+
+
+
+
+
+
+
+
diff --git a/public/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/index.html b/public/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/index.html
new file mode 100644
index 0000000..880c844
--- /dev/null
+++ b/public/tailscale-caddy-and-nixos-containers-a-match-made-in-heaven/index.html
@@ -0,0 +1,96 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ tailscale, caddy, and nixos containers - a match made in heaven
+
+
+
+
+ For a little while now I’ve been running some services (jellyfin etc.) on an old laptop in my house. I’m not trying to sound like a podcast ad but as a networking novice, the simplicity tailscale brings to accessing these services remotely is very nice. Until recently though, I had been accessing my services like a heathen with http and port numbers (eg http://tailscale-ip:service-port). This works and is perfectly secure thanks to tailscale though it lacks a certain finesse. In an ideal world you’d have a reverse proxy and set up SSL certs so your browser doesn’t get stressed and you dont have to rememeber ip addresses and port numbers.
+When I initially looked at how to do this it seemed like it was above my paygrade and not worth the stress; that was until I came across this . This works great and is as simple as advertised though there is one drawback: you can only reverse proxy one service per host. So for my usecase of the laptop with multiple services running on it I could only use the magic caddy tailscale auto-https thing for one of them.
+what to do?
+Seeing as I was already using nixos on my latop server I turned to a slightly cumbersome nixos solution. One nixos-container for each service I wanted over https. I’d be lying If I said I completely understand all of this NAT business but this was the config I cobbled together (copied from the nixos docs).
+ networking . nat = {
+ enable = true ;
+ internalInterfaces = [ "ve-+" ];
+ externalInterface = "ens3" ;
+ };
+
+ containers . jellyfin = {
+ autoStart = true ;
+ enableTun = true ;
+ privateNetwork = true ;
+ hostAddress = "192.168.100.10" ;
+ localAddress = "192.168.100.11" ;
+ bindMounts = {
+ "/films" = {
+ hostPath = "/mnt/films" ;
+ };
+ };
+
+ config = { pkgs , ... }: {
+
+ services . tailscale = {
+ enable = true ;
+ # permit caddy to get certs from tailscale
+ permitCertUid = "caddy" ;
+ };
+
+ services . jellyfin = {
+ enable = true ;
+ openFirewall = true ;
+ };
+
+ services . caddy = {
+ enable = true ;
+ extraConfig = ''
+
+ jellyfin.tailnet-name.ts.net {
+ reverse_proxy localhost:8096
+ }
+
+ '' ;
+ };
+
+
+ # open https port
+ networking . firewall . allowedTCPPorts = [ 443 ];
+
+ system . stateVersion = "23.05" ;
+
+ };
+ };
+ }
+This example enables the jellyfin, tailscale, and caddy services, mounts a film folder from the host, and lets the container talk to the internet.
+Once you’ve logged into the container sudo nixos-container root-login jellyfin and authenticated with tailscale sudo tailscale up, you should be able to access your jellyfin in your browser at https://jellyfin.tailnet-name.ts.net.
+As well as solving the multiple services problem, separating services onto their own hosts is nice if you want to share a particular service with someone else. I personaly feel happier just sharing one container running jellyfin rather than the whole host with multiple things on it. Anyway thanks for listening to my TED talk.
+
+
+
+
+
diff --git a/public/teeny-tiny-bash-fetch-script/index.html b/public/teeny-tiny-bash-fetch-script/index.html
new file mode 100644
index 0000000..5e41e1e
--- /dev/null
+++ b/public/teeny-tiny-bash-fetch-script/index.html
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ teeny tiny bash fetch script
+
+
+
+
+ This is my attempt at a neofetch, pfetch, whateverfetch style system info utility. My main concern was making something which looked nice, was easily configurable, and as portable as possible (I didn’t really try that hard with the portability). I didn’t think much about performance; I’m personally not a man who stresses too much when a command takes a quarter of a second instead of a tenth. The basic gameplan was to get an array of bash commands which would fetch various bits and bobs, then loop through this array formatting the text with ANSI escape codes. First things first, this was the associative array I came up with:
+declare -A fetch =(
+ [ user]= " $USER "
+ [ host]= " $( cat /etc/hostname) "
+ [ uptime]= " $( uptime | awk '{print $3}' | sed 's/:/h / ; s/,/m/' ) "
+ [ kernel]= " $( awk '{print $3}' /proc/version) "
+ [ distro]= " $( sed -n 's/^PRETTY_NAME="//p' /etc/os-release | sed 's/"//' ) "
+ [ shell]= " $( basename $SHELL ) "
+ [ de]= " $XDG_CURRENT_DESKTOP "
+ [ terminal]= " $TERM "
+ [ editor]= " $EDITOR "
+ [ root]= " $( df -Th / | tail -n 1 | awk '{print $6}' ) ,
+ $( df -Th / | tail -n 1 | awk '{print $2}' ) "
+ [ ip]= " $( host myip.opendns.com resolver1.opendns.com |
+ tail -n 1 | awk '{print $4}' ) "
+ [ battery]= " $( cat /sys/class/power_supply/BAT0/capacity) %"
+ [ cpu]= " $( sed -n 5p /proc/cpuinfo | cut -d: -f2) "
+ [ ram]= " $( free -h | sed -n 2p | awk '{print $3}' ) /
+ $( free -h | sed -n 2p | awk '{print $2}' ) "
+ [ swap]= " $( free -h | sed -n 3p | awk '{print $3}' ) /
+ $( free -h | sed -n 3p | awk '{print $2}' ) "
+ [ display]= " $( xrandr | grep '*' | awk '{print $1}' ) ,
+ $( xrandr | grep '*' | awk '{print $2}' | sed 's/*/Hz/ ; s/+//' ) "
+)
+Each of these elements fetches a differenet piece of info. You could just use environment variables to get quite a few things (user), some were an issue of grabbing a particular piece of info from a file (distro name), and some of the more complicated ones I just reformatted output from other commands (ram usage).
+Next order of business: colors. I wanted to put a chunk or randomly colored text at the start of each line so that each time you ran the command you got something that looked a little different. I made this array of escape codes each one referring to a different bold color:
+declare -a colors =(
+ "\e[0;1;30m" # black
+ "\e[0;1;31m" # red
+ "\e[0;1;32m" # green
+ "\e[0;1;33m" # blue
+ "\e[0;1;34m" # yellow
+ "\e[0;1;35m" # pink
+ "\e[0;1;36m" # magenta
+ "\e[0;1;37m" # white
+ )
+I then repurposed a nice function from someone on stackoverflow to get a random element from this array. The variable ‘pre’ here is the text that I want formatted:
+pre = "->"
+
+ random_color () {
+ size = ${# colors [@] }
+ index = $(( $RANDOM % $size ))
+ echo " ${ colors [ $index ] }${ pre } \e[0m"
+ }
+My plan was then to simply loop through the array, ’echo-ing’ out the random_color function, the key from the fetch array, a separator, and then the value form the fetch array. This worked mainly, the only issue being that each element from the fetch was not printed in the order it was declared. Ideally, I wanted the fetch elements to be printed in the order they were put in the array so you could configure the how they appeared. Once again my primitive understanding of bash had let me down; I turned to stackoverflow. I found the solution was to define another array containing the fetch keys and then use it to attack the other associative ‘fetch’ array:
+declare -a order =(
+ "user"
+ "host"
+ "uptime" # uses uptime command
+ "kernel"
+ "distro"
+ "shell"
+ "de"
+ "terminal"
+ "editor"
+ # "ip" # uses host command
+ # "cpu"
+ # "ram" # uses free command
+ # "swap" # uses free also
+ # "root" # uses df command
+ # "battery"
+ # "display" # uses xrandr
+ )
+
+ for info in " ${ order [@] } " ; do
+ echo -e " $( random_color) \e[0;1;3m $info \e[0m ${ sep }${ fetch [ $info ] } "
+ done
+This had the happy unintended consequence of allowing you to very easily configure which items you wanted in the fetch by simply commenting out keys from the order array. You can check out the script in its entirety here . This is a pretty picture of a few variations.
+
+
+
+
+
+
diff --git a/public/theming-nirvana/index.html b/public/theming-nirvana/index.html
new file mode 100644
index 0000000..41e5b23
--- /dev/null
+++ b/public/theming-nirvana/index.html
@@ -0,0 +1,128 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ theming nirvana
+
+
+
+
+ As I fall deeper and deeper down the nixos rabbit hole, I find myself becoming more and more obsessed with controlling every little thing on my computers declaratively. It starts with: ‘oh this is cool I can specify which desktop environment to use in my configuration.nix’. Next thing you know you’ve discovered home-manager and every program on every linux system you use needs to be controlled in your nix-config. Of course this slightly insane approach has its downsides; it also opens some doors though.
+Nix-colors lets you dyanmically change the theming of programs controlled in your nix config. So when you want to change the color of everything and have it match and all be pretty lol, you are able to do so with one word as opposed to poring over everything changing each individual color. For a certain type of person, this is very nice!
+how to make it work
+This will be a quick rundown of how I’ve got things set up; this is basically just a rehash of this .
+First of all, you need to add nix-colors to your flake inputs and then point home-manager in its direction. The relevant parts of my flake.nix look something like this.
+{
+ inputs = {
+ nix-colors . url = "github:misterio77/nix-colors" ;
+ };
+ homeConfigurations = {
+ "randy@computer" = home-manager . lib . homeManagerConfiguration {
+ extraSpecialArgs = { inherit nix-colors ; };
+ };
+ }
+Then you can import the module into your home-manager config, specify a scheme (available schemes here ), and get to theming.
+Here’s a simple example where I make my dunst notifications follow the everforest theme.
+{ pkgs , config , nix-colors , ... }: {
+
+ imports = [
+ nix-colors . homeManagerModule
+ ];
+
+ colorScheme = nix-colors . colorSchemes . everforest ;
+
+ services . dunst = {
+ enable = true ;
+ urgency_normal = {
+ background = "# ${ config . colorScheme . colors . base01 } " ;
+ foreground = "# ${ config . colorScheme . colors . base05 } " ;
+ };
+ };
+ }
+a couple of additional tips and tricks
+First tip and trick: generate and dynamically alter gtk themes depending on current nix-colors theme.
+{ config , pkgs , inputs , ... }:
+
+ let
+ inherit ( inputs . nix-colors . lib-contrib { inherit pkgs ; }) gtkThemeFromScheme ;
+ in rec {
+ gtk = {
+ enable = true ;
+ theme = {
+ name = " ${ config . colorScheme . slug } " ;
+ package = gtkThemeFromScheme { scheme = config . colorScheme ; };
+ };
+ };
+
+ services . xsettingsd = {
+ enable = true ;
+ settings = {
+ "Net/ThemeName" = " ${ gtk . theme . name } " ;
+ "Net/IconThemeName" = " ${ gtk . iconTheme . name } " ;
+ };
+ };
+ }
+Second tip and trick: if you’re not using nix to configure everything you can still pass your colors across in the relevant format with home.file. I do this for qtile.
+{ config , pkgs , ... }:
+ let
+ c = config . colorScheme . colors ;
+ in
+ {
+ home . file = {
+ ".config/qtile/colors.py" = {
+ text = ''
+ scheme = {
+ 'yellow': "# ${ c . base0A } ",
+ 'orange': "# ${ c . base09 } ",
+ 'red': "# ${ c . base0F } ",
+ 'magenta': "# ${ c . base08 } ",
+ 'violet': "# ${ c . base0E } ",
+ 'blue': "# ${ c . base0D } ",
+ 'cyan': "# ${ c . base0C } ",
+ 'green': "# ${ c . base0B } ",
+ }
+ '' ;
+ };
+ };
+ }
+You can then import the colors into your config.py and use them as you see fit.
+from colors import scheme
+
+ layouts = [
+ layout . MonadTall (
+ border_normal = scheme [ 'yellow' ],
+ border_focus = scheme [ 'green' ],
+ ),
+ ]
+That’s it for today. Thank you to the hero that made this.
+
+
+
+
+
diff --git a/public/translating-docker-to-nix/index.html b/public/translating-docker-to-nix/index.html
new file mode 100644
index 0000000..fc127b0
--- /dev/null
+++ b/public/translating-docker-to-nix/index.html
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ translating docker to nix?!
+
+
+
+
+ In my opinion, there are moments when the convenience of docker and its surrounding ecosystem can’t be beat. I’ve been dabbling in the self hosting world and oftentimes the best maintained packaging option is a docker image. As a result of this I’ve been playing around with the nixos approach to managing docker containers.
+nix -> docker compose -> docker run
+To illustrate how to translate a simple example from the world of docker to nix let’s have a look at the config for my searxng instance.
+virtualisation . oci-containers . containers . "searxng" = {
+ autoStart = true ;
+ image = "searxng/searxng" ;
+ volumes = [
+ "/srv/searx:/etc/searxng"
+ ];
+ environment = {
+ BASE_URL = "https://searx.jdysmcl.xyz/" ;
+ INSTANCE_NAME = "go on big boy dont be shy" ;
+ };
+ ports = [ "8080:8080" ];
+ };
+Here is the same thing written in a docker-compose.yml style format.
+services :
+ searxng :
+ image : searxng/searxng
+ volumes :
+ - /srv/searxng:/etc/searxng
+ environment :
+ - BASE_URL=https://searx.jdysmcl.xyz/;
+ - INSTANCE_NAME=go on big boy dont be shy;
+ ports :
+ - "8080:8080"
+ Also, this is what it would look like as a simple old docker run.
+$ docker pull searxng/searxng
+ $ docker run --rm \
+ -d -p 8080:8080 \
+ -v "/srv/searxng:/etc/searxng" \
+ -e "BASE_URL=http://searx.jdysmcl.xyz/" \
+ -e "INSTANCE_NAME=go on big boy dont be shy" \
+ searxng/searxng
+bits and bobs
+As you can see, nix very kindly provides you with convenient options for the most essential tasks: mounting volumes, exposing ports, passing environment variables etc. But what about some more niche configurations that aren’t exposed in oci-containers.nix . As far as I can tell, your best bet in these scenarios is virtualisation.oci-containers.containers.<name>.extraOptions; this lets you pass a list of command line arguments to your docker run command. For example, I had this in my config for a vpn container.
+virtualisation . oci-containers . containers . "vpn" . extraOptions = [
+ "--cap-add=net_admin"
+ "--device=/dev/net/tun"
+ "--network=bridge"
+ ];
+With a mishmash of these different bits and bobs I was able to do everything that I needed to. It doesn’t really open any more doors than docker compose but it’s nice to have the option when you’re already invested in the nix ecosystem.
+One final note: nix provides the option to choose between docker and podman with virtualisation.oci-containers.containers.backend. This defaults to podman.
+
+
+
+
+
diff --git a/public/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/index.html b/public/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/index.html
new file mode 100644
index 0000000..7bac38e
--- /dev/null
+++ b/public/upgrade-your-qtile-setup-with-a-cute-dropdown-terminal/index.html
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ upgrade your qtile setup with a cute dropdown terminal
+
+
+
+
+ I didn’t know you could do this until recently, very fun and playful little feature. How you want to do it will depend slightly on how you have your groups set up but I start with importing the relevant libraries and defining an empty list.
+from libqtile.config import Dropdown , Scratchpad
+
+ groups = []
+I’m then able to append all the groups I want to this list. For the dropdown terminal you need the ScratchPad group which to quote the qtile docs is a “special - by default invisible - group which acts as a container for DropDown configurations”. My configuration looks like this:
+groups . append (
+ ScratchPad ( "scratchpad" , [
+ DropDown (
+ "term" ,
+ kitty ,
+ opacity = 0.9 ,
+ ),
+ ]
+ ),
+ )
+This gives you a terminal (kitty in this case) with a little tranparency. By default, it will pop up with this size:
+
+Though this can easily be altered with the x, y, height, and width keys:
+groups . append (
+ ScratchPad ( "scratchpad" , [
+ DropDown (
+ "term" ,
+ kitty ,
+ opacity = 0.9 ,
+ x = 0 ,
+ y = 0 ,
+ width = 0.3 ,
+ height = 0.5 ,
+ ),
+ ])
+ )
+This gives us a little boxy guy in the top left corner:
+
+We also have the option to set keybindings to toggle the appearance of the window. I’ve got this in my config.py now:
+keys = [
+ Key ([ m , "shift" ], "Return" ,
+ lazy . group [ "scratchpad" ] . dropdown_toggle ( "terminal" ),
+ desc = 'dropdown term'
+ ),
+ ]
+Anyway, hope this was useful, happy configurating :)
+
+
+
+
+
diff --git a/public/vanilla-javascript-theme-toggle-for-simpletons/index.html b/public/vanilla-javascript-theme-toggle-for-simpletons/index.html
new file mode 100644
index 0000000..032bd1d
--- /dev/null
+++ b/public/vanilla-javascript-theme-toggle-for-simpletons/index.html
@@ -0,0 +1,114 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ vanilla javascript theme toggle for simpletons
+
+
+
+
+ Sometimes when I’m trawling the internet and happen upon a particularly nice looking website, I develop css and javascript FOMO. The thing I’ve been lusting after above all else is one of those fancy little dark theme toggle buttons. As you can probably tell from the website you’re looking at my web dev skills are limited. As a result of this I had assumed such niceties were out of reach.
+Last week though I decided it was time for this to change! I would do a teeny bit of javascript. I could have nice things. This is a rundown of the very simple implementation I came up with.
+HTML
+First things first, we’ll need a button for users to click. This can be plopped wherever you want on your site.
+< button id = "themeButton" onclick = "toggleTheme()" class = "theme-button" >
+The id will let us reference the button from our javascript, onclick tells the button to call the toggleTheme() function we’ll write in a minute, and the theme-button class will let us theme the button from our css.
+CSS
+In order to achieve our magic theme switching we’re going to split our css out in to three files: base.css, dark.css, and light.css. The dark.css and light.css files will do the same thing: import all the common css and define a root pseudo-class to store our color variables. For example a very simple dark.css would look like this.
+/* import common css */
+@ import url ( "base.css" ) ;
+
+ /* define colors */
+: root {
+ --bg : black ;
+ --fg : white ;
+ }
+The base.css will simply store all the other styling you want. Here you can reference the color variables defined in the dark.css and light.css.
+body {
+ background-color : var ( -- bg );
+ color : var ( -- fg );
+ }
+JS
+Now with the groundwork in place we can stick it all together with the javascript. The gameplan here is to check the href attribute of the stylesheet element. Then if it’s set to dark.css switch it to light.css and vice-versa. my toggleTheme function looked like this.
+function toggleTheme () {
+
+ var stylesheet = document . getElementById ( 'stylesheet' );
+
+ if ( stylesheet . getAttribute ( 'href' ) === '/dark.css' ) {
+
+ // update stylesheet
+ stylesheet . setAttribute ( 'href' , '/light.css' );
+
+ } else {
+
+ // update stylesheet
+ stylesheet . setAttribute ( 'href' , '/dark.css' );
+
+ }
+ }
+This works well except for one little problem: when you refresh or load a new page, the stylesheet is returned to its default. This short term memory can be fixed though so theme changes persist through page loads.
+First we need to update our toggleTheme function to store our theme changes locally.
+function toggleTheme () {
+
+ var stylesheet = document . getElementById ( 'stylesheet' );
+
+ if ( stylesheet . getAttribute ( 'href' ) === '/dark.css' ) {
+
+ // update stylesheet
+ stylesheet . setAttribute ( 'href' , '/light.css' );
+ // store theme
+ localStorage . setItem ( 'stylesheet' , '/light.css' );
+
+ } else {
+
+ // update stylesheet
+ stylesheet . setAttribute ( 'href' , '/dark.css' );
+ // store theme
+ localStorage . setItem ( 'stylesheet' , '/dark.css' );
+
+ }
+ }
+We then add an event listener to check if there is a theme stored on page loads.
+window . addEventListener ( 'load' , function () {
+
+ // get stored style
+ var storedStyle = localStorage . getItem ( 'stylesheet' );
+ var stylesheet = document . getElementById ( 'stylesheet' );
+
+ // set stored style if it exists
+ if ( storedStyle ) {
+ stylesheet . setAttribute ( 'href' , storedStyle );
+ }
+ });
+Finally, don’t forget to add your javascript to your html somewhere.
+< script src = "/toggle.js" ></ script >
+Hope you’ve enjoyed. Toggle toggle toggle!
+
+
+
+
+
diff --git a/static/favicon.ico b/static/favicon.ico
new file mode 100644
index 0000000..67b8d29
Binary files /dev/null and b/static/favicon.ico differ
diff --git a/static/image/dropdown.png b/static/image/dropdown.png
new file mode 100644
index 0000000..d617a6e
Binary files /dev/null and b/static/image/dropdown.png differ
diff --git a/static/image/dropdown.webp b/static/image/dropdown.webp
new file mode 100644
index 0000000..95a2d89
Binary files /dev/null and b/static/image/dropdown.webp differ
diff --git a/static/image/dropdown2.png b/static/image/dropdown2.png
new file mode 100644
index 0000000..3f4d3cc
Binary files /dev/null and b/static/image/dropdown2.png differ
diff --git a/static/image/dropdown2.webp b/static/image/dropdown2.webp
new file mode 100644
index 0000000..4f9b7df
Binary files /dev/null and b/static/image/dropdown2.webp differ
diff --git a/static/image/emacs.png b/static/image/emacs.png
new file mode 100644
index 0000000..78f40e5
Binary files /dev/null and b/static/image/emacs.png differ
diff --git a/static/image/golazo.png b/static/image/golazo.png
new file mode 100644
index 0000000..eee6635
Binary files /dev/null and b/static/image/golazo.png differ
diff --git a/static/image/output.webp b/static/image/output.webp
new file mode 100644
index 0000000..f95ea91
Binary files /dev/null and b/static/image/output.webp differ
diff --git a/static/image/pgn.webp b/static/image/pgn.webp
new file mode 100644
index 0000000..a7bf25b
Binary files /dev/null and b/static/image/pgn.webp differ
diff --git a/themes/etch/LICENSE b/themes/etch/LICENSE
new file mode 100644
index 0000000..37209a9
--- /dev/null
+++ b/themes/etch/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2020 Lukas Joswiak
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/themes/etch/README.md b/themes/etch/README.md
new file mode 100644
index 0000000..e46750b
--- /dev/null
+++ b/themes/etch/README.md
@@ -0,0 +1,33 @@
+# Etch
+
+Etch is a simple, responsive theme for [Hugo](https://gohugo.io) with a focus on writing. A live demo is available at https://lukasjoswiak.github.io/etch/.
+
+
+
+## Features:
+
+* Homepage with list of posts.
+* Support for pages.
+* Responsive design for optimized mobile experience.
+* Syntax highlighting with customizable theme.
+* Dark theme which automatically adjusts based on users' setting ([example](https://github.com/LukasJoswiak/etch/wiki/Dark-mode)).
+* No external dependencies, no JavaScript, no web fonts.
+* Internationalization friendly: use default English translations or create your own
+
+## Installation
+
+To install `etch`, download the repository into the `themes` folder in the root of your site.
+
+```
+$ git submodule add https://github.com/LukasJoswiak/etch.git themes/etch
+```
+
+Then, use the theme to generate your site.
+
+```
+$ hugo server -t etch
+```
+
+Use the [sample configuration](https://github.com/LukasJoswiak/etch/wiki/Configuration#sample-configuration) as a starting point. See the [configuration](https://github.com/LukasJoswiak/etch/wiki/Configuration) page for more info.
+
+Read the [wiki](https://github.com/LukasJoswiak/etch/wiki) to learn about more options.
diff --git a/themes/etch/archetypes/default.md b/themes/etch/archetypes/default.md
new file mode 100644
index 0000000..ac36e06
--- /dev/null
+++ b/themes/etch/archetypes/default.md
@@ -0,0 +1,2 @@
++++
++++
diff --git a/themes/etch/assets/css/dark.css b/themes/etch/assets/css/dark.css
new file mode 100644
index 0000000..8007b2f
--- /dev/null
+++ b/themes/etch/assets/css/dark.css
@@ -0,0 +1,53 @@
+{{ if not (eq .Site.Params.dark "on") -}}
+@media (prefers-color-scheme: dark) {
+{{ end -}}
+html {
+ scrollbar-color: #6c6c6c #2e2e2e;
+}
+
+body {
+ color: #ebebeb;
+ background: #121212;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+header#banner a {
+ color: #e0e0e0;
+ text-decoration: none;
+}
+
+header#banner nav ul li a {
+ color: #cccccc;
+}
+
+main#content a {
+ color: #00b1ed;
+}
+
+main#content p {
+ color: #f5f5f5;
+}
+
+main#content hr {
+ background: #5c5c5c;
+}
+
+main#content #toc h4 {
+ color: #d4d4d4;
+}
+
+main#content ul#posts small {
+ color: #a7a7a7;
+}
+
+main#content ul#posts li a:hover {
+ color: #21c7ff;
+}
+
+main#content header#post-header div {
+ color: #a7a7a7;
+}
+{{- if not (eq .Site.Params.dark "on") -}}
+}
+{{- end -}}
diff --git a/themes/etch/assets/css/main.css b/themes/etch/assets/css/main.css
new file mode 100644
index 0000000..4c2f2ea
--- /dev/null
+++ b/themes/etch/assets/css/main.css
@@ -0,0 +1,282 @@
+*, *:before, *:after {
+ box-sizing: border-box;
+}
+
+html {
+ font-size: 62.5%;
+}
+
+body {
+ font-size: 16px;
+ font-size: 1.6rem;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
+ color: #313a3d;
+ width: 100%;
+ margin: 0 auto;
+ padding: 0 16px;
+ line-height: 1.6;
+ overflow-wrap: break-word;
+}
+
+header#banner {
+ margin: 25px 0;
+}
+
+header#banner a {
+ color: #313a3d;
+ text-decoration: none;
+}
+
+header#banner a:hover {
+ text-decoration: underline;
+}
+
+header#banner h2 {
+ display: inline;
+ font-size: 21px;
+ font-size: 2.1rem;
+ margin: 0 8px 0 0;
+}
+
+header#banner nav {
+ display: inline-block;
+}
+
+header#banner nav ul {
+ list-style-type: none;
+ font-size: 1.05em;
+ text-transform: lowercase;
+ margin: 0;
+ padding: 0;
+}
+
+header#banner nav ul li {
+ display: inline;
+ margin: 0 3px;
+}
+
+header#banner nav ul li a {
+ color: #454545;
+}
+
+main#content a {
+ color: #007dfa;
+ text-decoration: none;
+}
+
+main#content a:hover {
+ text-decoration: underline;
+}
+
+main#content h1,
+main#content h2,
+main#content h3,
+main#content h4,
+main#content h5,
+main#content h6 {
+ margin-bottom: 0;
+ line-height: 1.15;
+}
+
+main#content h3 {
+ font-size: 19px;
+ font-size: 1.9rem;
+}
+
+main#content h1 + p,
+main#content h2 + p,
+main#content h3 + p,
+main#content h4 + p,
+main#content h5 + p,
+main#content h6 + p {
+ margin-top: 5px;
+}
+
+main#content p {
+ color: #394548;
+ margin: 16px 0;
+}
+
+main#content hr {
+ height: 1px;
+ border: 0;
+ background: #d8d8d8;
+}
+
+main#content abbr {
+ cursor: help;
+}
+
+/* index.html styles */
+main#content ul#posts {
+ list-style-type: none;
+ font-size: 16px;
+ font-size: 1.6rem;
+ margin-top: 0;
+ padding: 0;
+}
+
+main#content ul#posts li {
+ margin: 5px 0;
+ padding: 0;
+}
+
+main#content ul#posts small {
+ font-size: 0.8em;
+ color: #767676;
+ margin-left: 10px;
+}
+
+main#content ul#posts li a {
+ text-decoration: none;
+}
+
+main#content ul#posts li a:hover {
+ color: #369aff;
+}
+
+main#content ul#posts li a:hover small {
+ color: inherit;
+}
+
+/* single.html styles */
+main#content header#post-header h1 {
+ display: block;
+ font-size: 23px;
+ font-size: 2.3rem;
+ font-weight: 600;
+ line-height: 1.15;
+}
+
+main#content header#post-header > div {
+ display: block;
+ font-size: 0.85em;
+ color: #767676;
+}
+
+main#content #toc {
+ border: 1px solid #b1b1b1;
+ border-radius: 1px;
+ line-height: 26px;
+ margin: 16px 0;
+ padding: 9px 14px;
+}
+
+main#content #toc h4 {
+ font-size: 1.06em;
+ color: #3d3d3d;
+ margin: 0;
+}
+
+main#content #toc nav#TableOfContents {
+ margin-top: 4px;
+}
+
+main#content #toc nav#TableOfContents > ul, main#content #toc nav#TableOfContents > ol {
+ margin-left: -40px;
+}
+
+main#content #toc ul, main#content #toc ol {
+ font-size: 0.98em;
+ margin: 0;
+ padding: 0 0 0 40px;
+}
+
+main#content #toc ul {
+ list-style-type: none;
+}
+
+main#content #toc ol {
+ counter-reset: item;
+}
+
+main#content #toc ol li {
+ display: block;
+}
+
+main#content #toc ol li:before {
+ content: counters(item, ".") ". ";
+ counter-increment: item;
+}
+
+main#content img {
+ max-width: 100%;
+ margin: 0 auto;
+}
+
+main#content figure {
+ margin: 16px 0;
+}
+
+main#content figure img {
+ display: block;
+ max-width: 100%;
+ margin: 0 auto;
+}
+
+main#content figure figcaption {
+ font-size: 0.92em;
+ font-style: italic;
+ line-height: 22px;
+ text-align: center;
+ margin-top: 6px;
+ padding: 0 10px;
+}
+
+main#content figure figcaption h4 {
+ font-style: normal;
+ display: inline;
+ margin: 0;
+}
+
+main#content figure figcaption p {
+ display: inline;
+ margin: 0;
+ padding-left: 8px;
+}
+
+main#content blockquote {
+ font-style: italic;
+ margin-top: 10px;
+ margin-bottom: 10px;
+ margin-left: 50px;
+ padding-left: 15px;
+ border-left: 3px solid #ccc;
+}
+
+main#content code,
+main#content pre {
+ font-family: 'Menlo', monospace;
+}
+
+main#content code {
+ font-size: 0.96em;
+ padding: 0 5px;
+}
+
+main#content pre {
+ display: block;
+ overflow-x: auto;
+ font-size: 14px;
+ font-size: 1.4rem;
+ white-space: pre;
+ margin: 20px 0;
+ padding: 1.5rem 1.5rem;
+ line-height: 1.4;
+}
+
+main#content pre code {
+ padding: 0;
+}
+
+main#content .footnotes {
+ font-size: 0.9em;
+}
+
+footer#footer {
+ font-size: 14px;
+ font-size: 1.4rem;
+ font-weight: 400;
+ color: #b3b3b3;
+ margin: 40px 0;
+}
diff --git a/themes/etch/assets/css/min770px.css b/themes/etch/assets/css/min770px.css
new file mode 100644
index 0000000..076fdee
--- /dev/null
+++ b/themes/etch/assets/css/min770px.css
@@ -0,0 +1,52 @@
+@media (min-width: 770px) {
+body {
+ width: 600px;
+ line-height: 1.5;
+}
+
+main#content hr {
+ width: 108%;
+ margin-left: -3.8%;
+}
+
+/* index.html styles */
+header#banner h2 {
+ font-size: 25px;
+ font-size: 2.5rem;
+}
+
+main#content h3 {
+ font-size: 20px;
+ font-size: 2rem;
+}
+
+main#content ul#posts {
+ font-size: 18px;
+ font-size: 1.8rem;
+}
+
+/* single.html styles */
+main#content header#post-header h1 {
+ font-size: 24px;
+ font-size: 2.4rem;
+}
+
+main#content img {
+ max-width: 108%;
+ margin-left: -3.8%;
+}
+
+main#content figure {
+ margin-left: -3.8%;
+}
+
+main#content figure img {
+ max-width: 108%;
+}
+
+main#content pre {
+ width: 108%;
+ margin-left: -3.8%;
+ padding: 1.5rem 2.2rem;
+}
+}
diff --git a/themes/etch/assets/css/syntax.css b/themes/etch/assets/css/syntax.css
new file mode 100644
index 0000000..350286e
--- /dev/null
+++ b/themes/etch/assets/css/syntax.css
@@ -0,0 +1,59 @@
+/* Background */ .chroma { color: #f8f8f2; background-color: #272822 }
+/* Error */ .chroma .err { color: #960050; background-color: #1e0010 }
+/* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; }
+/* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; width: auto; overflow: auto; display: block; }
+/* LineHighlight */ .chroma .hl { display: block; width: 100%;background-color: #ffffcc }
+/* LineNumbersTable */ .chroma .lnt { margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }
+/* LineNumbers */ .chroma .ln { margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }
+/* Keyword */ .chroma .k { color: #66d9ef }
+/* KeywordConstant */ .chroma .kc { color: #66d9ef }
+/* KeywordDeclaration */ .chroma .kd { color: #66d9ef }
+/* KeywordNamespace */ .chroma .kn { color: #f92672 }
+/* KeywordPseudo */ .chroma .kp { color: #66d9ef }
+/* KeywordReserved */ .chroma .kr { color: #66d9ef }
+/* KeywordType */ .chroma .kt { color: #66d9ef }
+/* NameAttribute */ .chroma .na { color: #a6e22e }
+/* NameClass */ .chroma .nc { color: #a6e22e }
+/* NameConstant */ .chroma .no { color: #66d9ef }
+/* NameDecorator */ .chroma .nd { color: #a6e22e }
+/* NameException */ .chroma .ne { color: #a6e22e }
+/* NameFunction */ .chroma .nf { color: #a6e22e }
+/* NameOther */ .chroma .nx { color: #a6e22e }
+/* NameTag */ .chroma .nt { color: #f92672 }
+/* Literal */ .chroma .l { color: #ae81ff }
+/* LiteralDate */ .chroma .ld { color: #e6db74 }
+/* LiteralString */ .chroma .s { color: #e6db74 }
+/* LiteralStringAffix */ .chroma .sa { color: #e6db74 }
+/* LiteralStringBacktick */ .chroma .sb { color: #e6db74 }
+/* LiteralStringChar */ .chroma .sc { color: #e6db74 }
+/* LiteralStringDelimiter */ .chroma .dl { color: #e6db74 }
+/* LiteralStringDoc */ .chroma .sd { color: #e6db74 }
+/* LiteralStringDouble */ .chroma .s2 { color: #e6db74 }
+/* LiteralStringEscape */ .chroma .se { color: #ae81ff }
+/* LiteralStringHeredoc */ .chroma .sh { color: #e6db74 }
+/* LiteralStringInterpol */ .chroma .si { color: #e6db74 }
+/* LiteralStringOther */ .chroma .sx { color: #e6db74 }
+/* LiteralStringRegex */ .chroma .sr { color: #e6db74 }
+/* LiteralStringSingle */ .chroma .s1 { color: #e6db74 }
+/* LiteralStringSymbol */ .chroma .ss { color: #e6db74 }
+/* LiteralNumber */ .chroma .m { color: #ae81ff }
+/* LiteralNumberBin */ .chroma .mb { color: #ae81ff }
+/* LiteralNumberFloat */ .chroma .mf { color: #ae81ff }
+/* LiteralNumberHex */ .chroma .mh { color: #ae81ff }
+/* LiteralNumberInteger */ .chroma .mi { color: #ae81ff }
+/* LiteralNumberIntegerLong */ .chroma .il { color: #ae81ff }
+/* LiteralNumberOct */ .chroma .mo { color: #ae81ff }
+/* Operator */ .chroma .o { color: #f92672 }
+/* OperatorWord */ .chroma .ow { color: #f92672 }
+/* Comment */ .chroma .c { color: #75715e }
+/* CommentHashbang */ .chroma .ch { color: #75715e }
+/* CommentMultiline */ .chroma .cm { color: #75715e }
+/* CommentSingle */ .chroma .c1 { color: #75715e }
+/* CommentSpecial */ .chroma .cs { color: #75715e }
+/* CommentPreproc */ .chroma .cp { color: #75715e }
+/* CommentPreprocFile */ .chroma .cpf { color: #75715e }
+/* GenericDeleted */ .chroma .gd { color: #f92672 }
+/* GenericEmph */ .chroma .ge { font-style: italic }
+/* GenericInserted */ .chroma .gi { color: #a6e22e }
+/* GenericStrong */ .chroma .gs { font-weight: bold }
+/* GenericSubheading */ .chroma .gu { color: #75715e }
diff --git a/themes/etch/exampleSite/config.toml b/themes/etch/exampleSite/config.toml
new file mode 100644
index 0000000..527434a
--- /dev/null
+++ b/themes/etch/exampleSite/config.toml
@@ -0,0 +1,38 @@
+baseURL = "https://example.com"
+title = "Website Name"
+theme = "etch"
+languageCode = "en-US"
+enableInlineShortcodes = true
+pygmentsCodeFences = true
+pygmentsUseClasses = true
+
+[params]
+ description = "Your site description"
+ copyright = "Copyright © 2021 Your Name"
+ dark = "auto"
+ highlight = true
+
+[menu]
+ [[menu.main]]
+ identifier = "posts"
+ name = "posts"
+ title = "posts"
+ url = "/"
+ weight = 10
+
+ [[menu.main]]
+ identifier = "about"
+ name = "about"
+ title = "about"
+ url = "/about/"
+ weight = 20
+
+[permalinks]
+ posts = "/:title/"
+
+[markup.goldmark.renderer]
+ # Allow HTML in Markdown
+ unsafe = true
+
+ [markup.tableOfContents]
+ ordered = true
diff --git a/themes/etch/exampleSite/content/_index.md b/themes/etch/exampleSite/content/_index.md
new file mode 100644
index 0000000..2a74490
--- /dev/null
+++ b/themes/etch/exampleSite/content/_index.md
@@ -0,0 +1,4 @@
+---
+title: "Home"
+---
+This is some info about me.
diff --git a/themes/etch/exampleSite/content/about/index.md b/themes/etch/exampleSite/content/about/index.md
new file mode 100644
index 0000000..eb5384b
--- /dev/null
+++ b/themes/etch/exampleSite/content/about/index.md
@@ -0,0 +1,21 @@
++++
+title = "About"
++++
+
+Written in Go, Hugo is an open source static site generator available under the [Apache Licence 2.0.](https://github.com/gohugoio/hugo/blob/master/LICENSE) Hugo supports TOML, YAML and JSON data file types, Markdown and HTML content files and uses shortcodes to add rich content. Other notable features are taxonomies, multilingual mode, image processing, custom output formats, HTML/CSS/JS minification and support for Sass SCSS workflows.
+
+Hugo makes use of a variety of open source projects including:
+
+* https://github.com/yuin/goldmark
+* https://github.com/alecthomas/chroma
+* https://github.com/muesli/smartcrop
+* https://github.com/spf13/cobra
+* https://github.com/spf13/viper
+
+Hugo is ideal for blogs, corporate websites, creative portfolios, online magazines, single page applications or even a website with thousands of pages.
+
+Hugo is for people who want to hand code their own website without worrying about setting up complicated runtimes, dependencies and databases.
+
+Websites built with Hugo are extremelly fast, secure and can be deployed anywhere including, AWS, GitHub Pages, Heroku, Netlify and any other hosting provider.
+
+Learn more and contribute on [GitHub](https://github.com/gohugoio).
diff --git a/themes/etch/exampleSite/content/posts/emoji-support.md b/themes/etch/exampleSite/content/posts/emoji-support.md
new file mode 100644
index 0000000..ecf6c86
--- /dev/null
+++ b/themes/etch/exampleSite/content/posts/emoji-support.md
@@ -0,0 +1,47 @@
++++
+author = "Hugo Authors"
+title = "Emoji Support"
+date = "2019-03-05"
+description = "Guide to emoji usage in Hugo"
+tags = [
+ "emoji",
+]
++++
+
+Emoji can be enabled in a Hugo project in a number of ways.
+
+The [`emojify`](https://gohugo.io/functions/emojify/) function can be called directly in templates or [Inline Shortcodes](https://gohugo.io/templates/shortcode-templates/#inline-shortcodes).
+
+To enable emoji globally, set `enableEmoji` to `true` in your site’s [configuration](https://gohugo.io/getting-started/configuration/) and then you can type emoji shorthand codes directly in content files; e.g.
+
+
+🙈 :see_no_evil: 🙉 :hear_no_evil: 🙊 :speak_no_evil:
+
+
+The [Emoji cheat sheet](http://www.emoji-cheat-sheet.com/) is a useful reference for emoji shorthand codes.
+
+***
+
+**N.B.** The above steps enable Unicode Standard emoji characters and sequences in Hugo, however the rendering of these glyphs depends on the browser and the platform. To style the emoji you can either use a third party emoji font or a font stack; e.g.
+
+{{< highlight html >}}
+.emoji {
+font-family: Apple Color Emoji,Segoe UI Emoji,NotoColorEmoji,Segoe UI Symbol,Android Emoji,EmojiSymbols;
+}
+{{< /highlight >}}
+
+{{< css.inline >}}
+
+{{< /css.inline >}}
\ No newline at end of file
diff --git a/themes/etch/exampleSite/content/posts/markdown-syntax.md b/themes/etch/exampleSite/content/posts/markdown-syntax.md
new file mode 100644
index 0000000..d60c404
--- /dev/null
+++ b/themes/etch/exampleSite/content/posts/markdown-syntax.md
@@ -0,0 +1,147 @@
++++
+author = "Hugo Authors"
+title = "Markdown Syntax Guide"
+date = "2019-03-11"
+description = "Sample article showcasing basic Markdown syntax and formatting for HTML elements."
+tags = [
+ "markdown",
+ "css",
+ "html",
+ "themes",
+]
+categories = [
+ "themes",
+ "syntax",
+]
+series = ["Themes Guide"]
+aliases = ["migrate-from-jekyl"]
++++
+
+This article offers a sample of basic Markdown syntax that can be used in Hugo content files, also it shows whether basic HTML elements are decorated with CSS in a Hugo theme.
+
+
+## Headings
+
+The following HTML ``—`` elements represent six levels of section headings. `` is the highest section level while `` is the lowest.
+
+# H1
+## H2
+### H3
+#### H4
+##### H5
+###### H6
+
+## Paragraph
+
+Xerum, quo qui aut unt expliquam qui dolut labo. Aque venitatiusda cum, voluptionse latur sitiae dolessi aut parist aut dollo enim qui voluptate ma dolestendit peritin re plis aut quas inctum laceat est volestemque commosa as cus endigna tectur, offic to cor sequas etum rerum idem sintibus eiur? Quianimin porecus evelectur, cum que nis nust voloribus ratem aut omnimi, sitatur? Quiatem. Nam, omnis sum am facea corem alique molestrunt et eos evelece arcillit ut aut eos eos nus, sin conecerem erum fuga. Ri oditatquam, ad quibus unda veliamenimin cusam et facea ipsamus es exerum sitate dolores editium rerore eost, temped molorro ratiae volorro te reribus dolorer sperchicium faceata tiustia prat.
+
+Itatur? Quiatae cullecum rem ent aut odis in re eossequodi nonsequ idebis ne sapicia is sinveli squiatum, core et que aut hariosam ex eat.
+
+## Blockquotes
+
+The blockquote element represents content that is quoted from another source, optionally with a citation which must be within a `footer` or `cite` element, and optionally with in-line changes such as annotations and abbreviations.
+
+#### Blockquote without attribution
+
+> Tiam, ad mint andaepu dandae nostion secatur sequo quae.
+> **Note** that you can use *Markdown syntax* within a blockquote.
+
+#### Blockquote with attribution
+
+> Don't communicate by sharing memory, share memory by communicating.
+> — Rob Pike[^1]
+
+
+[^1]: The above quote is excerpted from Rob Pike's [talk](https://www.youtube.com/watch?v=PAAkCSZUG1c) during Gopherfest, November 18, 2015.
+
+## Tables
+
+Tables aren't part of the core Markdown spec, but Hugo supports supports them out-of-the-box.
+
+ Name | Age
+--------|------
+ Bob | 27
+ Alice | 23
+
+#### Inline Markdown within tables
+
+| Inline | Markdown | In | Table |
+| ---------- | --------- | ----------------- | ---------- |
+| *italics* | **bold** | ~~strikethrough~~ | `code` |
+
+## Code Blocks
+
+#### Code block with backticks
+
+```
+html
+
+
+
+
+ Example HTML5 Document
+
+
+ Test
+
+
+```
+#### Code block indented with four spaces
+
+
+
+
+
+ Example HTML5 Document
+
+
+ Test
+
+
+
+#### Code block with Hugo's internal highlight shortcode
+{{< highlight html >}}
+
+
+
+
+ Example HTML5 Document
+
+
+ Test
+
+
+{{< /highlight >}}
+
+## List Types
+
+#### Ordered List
+
+1. First item
+2. Second item
+3. Third item
+
+#### Unordered List
+
+* List item
+* Another item
+* And another item
+
+#### Nested list
+
+* Item
+1. First Sub-item
+2. Second Sub-item
+
+## Other Elements — abbr, sub, sup, kbd, mark
+
+GIF is a bitmap image format.
+
+H2 O
+
+Xn + Yn = Zn
+
+Press CTRL +ALT +Delete to end the session.
+
+Most salamanders are nocturnal, and hunt for insects, worms, and other small creatures.
+
diff --git a/themes/etch/exampleSite/content/posts/placeholder-text.md b/themes/etch/exampleSite/content/posts/placeholder-text.md
new file mode 100644
index 0000000..378b995
--- /dev/null
+++ b/themes/etch/exampleSite/content/posts/placeholder-text.md
@@ -0,0 +1,58 @@
++++
+author = "Hugo Authors"
+title = "Placeholder Text"
+date = "2019-03-09"
+description = "Lorem Ipsum Dolor Si Amet"
+tags = [
+ "markdown",
+ "text",
+]
++++
+
+Lorem est tota propiore conpellat pectoribus de
+pectora summo. Redit teque digerit hominumque toris verebor lumina non cervice
+subde tollit usus habet Arctonque, furores quas nec ferunt. Quoque montibus nunc
+caluere tempus inhospita parcite confusaque translucet patri vestro qui optatis
+lumine cognoscere flos nubis! Fronde ipsamque patulos Dryopen deorum.
+
+1. Exierant elisi ambit vivere dedere
+2. Duce pollice
+3. Eris modo
+4. Spargitque ferrea quos palude
+
+Rursus nulli murmur; hastile inridet ut ab gravi sententia! Nomine potitus
+silentia flumen, sustinet placuit petis in dilapsa erat sunt. Atria
+tractus malis.
+
+1. Comas hunc haec pietate fetum procerum dixit
+2. Post torum vates letum Tiresia
+3. Flumen querellas
+4. Arcanaque montibus omnes
+5. Quidem et
+
+# Vagus elidunt
+
+
+
+[The Van de Graaf Canon](https://en.wikipedia.org/wiki/Canons_of_page_construction#Van_de_Graaf_canon)
+
+## Mane refeci capiebant unda mulcebat
+
+Victa caducifer, malo vulnere contra
+dicere aurato, ludit regale, voca! Retorsit colit est profanae esse virescere
+furit nec; iaculi matertera et visa est, viribus. Divesque creatis, tecta novat collumque vulnus est, parvas. **Faces illo pepulere** tempus adest. Tendit flamma, ab opes virum sustinet, sidus sequendo urbis.
+
+Iubar proles corpore raptos vero auctor imperium; sed et huic: manus caeli
+Lelegas tu lux. Verbis obstitit intus oblectamina fixis linguisque ausus sperare
+Echionides cornuaque tenent clausit possit. Omnia putatur. Praeteritae refert
+ausus; ferebant e primus lora nutat, vici quae mea ipse. Et iter nil spectatae
+vulnus haerentia iuste et exercebat, sui et.
+
+Eurytus Hector, materna ipsumque ut Politen, nec, nate, ignari, vernum cohaesit sequitur. Vel **mitis temploque** vocatus, inque alis, *oculos nomen* non silvis corpore coniunx ne displicet illa. Crescunt non unus, vidit visa quantum inmiti flumina mortis facto sic: undique a alios vincula sunt iactata abdita! Suspenderat ego fuit tendit: luna, ante urbem
+Propoetides **parte**.
+
+{{< css.inline >}}
+
+{{< /css.inline >}}
diff --git a/themes/etch/exampleSite/content/posts/rich-content.md b/themes/etch/exampleSite/content/posts/rich-content.md
new file mode 100644
index 0000000..8cb8861
--- /dev/null
+++ b/themes/etch/exampleSite/content/posts/rich-content.md
@@ -0,0 +1,34 @@
++++
+author = "Hugo Authors"
+title = "Rich Content"
+date = "2019-03-10"
+description = "A brief description of Hugo Shortcodes"
+tags = [
+ "shortcodes",
+ "privacy",
+]
++++
+
+Hugo ships with several [Built-in Shortcodes](https://gohugo.io/content-management/shortcodes/#use-hugo-s-built-in-shortcodes) for rich content, along with a [Privacy Config](https://gohugo.io/about/hugo-and-gdpr/) and a set of Simple Shortcodes that enable static and no-JS versions of various social media embeds.
+
+---
+
+## YouTube Privacy Enhanced Shortcode
+
+{{< youtube ZJthWmvUzzc >}}
+
+
+
+---
+
+## Twitter Shortcode
+
+{{< tweet user="DesignReviewed" id="1085870671291310081" >}}
+
+
+
+---
+
+## Vimeo Simple Shortcode
+
+{{< vimeo_simple 48912912 >}}
diff --git a/themes/etch/i18n/en.toml b/themes/etch/i18n/en.toml
new file mode 100644
index 0000000..e30f8ce
--- /dev/null
+++ b/themes/etch/i18n/en.toml
@@ -0,0 +1,19 @@
+# Learn how to use Date format (date, created, updated)
+# -> https://gohugo.io/functions/dateformat/
+
+[posts]
+
+[posts.title]
+other = "Posts"
+
+[posts.date]
+other = "Jan 2, 2006"
+
+
+[post]
+
+[post.created]
+other = "January 2, 2006"
+
+[post.updated]
+other = "Updated January 2, 2006"
diff --git a/themes/etch/images/screenshot.png b/themes/etch/images/screenshot.png
new file mode 100644
index 0000000..fed9553
Binary files /dev/null and b/themes/etch/images/screenshot.png differ
diff --git a/themes/etch/images/screenshot_dark.png b/themes/etch/images/screenshot_dark.png
new file mode 100644
index 0000000..11505f9
Binary files /dev/null and b/themes/etch/images/screenshot_dark.png differ
diff --git a/themes/etch/images/screenshot_small.png b/themes/etch/images/screenshot_small.png
new file mode 100644
index 0000000..d320a7c
Binary files /dev/null and b/themes/etch/images/screenshot_small.png differ
diff --git a/themes/etch/images/tn.png b/themes/etch/images/tn.png
new file mode 100644
index 0000000..0556f24
Binary files /dev/null and b/themes/etch/images/tn.png differ
diff --git a/themes/etch/images/tn_dark.png b/themes/etch/images/tn_dark.png
new file mode 100644
index 0000000..b40629b
Binary files /dev/null and b/themes/etch/images/tn_dark.png differ
diff --git a/themes/etch/layouts/404.html b/themes/etch/layouts/404.html
new file mode 100644
index 0000000..e69de29
diff --git a/themes/etch/layouts/_default/baseof.html b/themes/etch/layouts/_default/baseof.html
new file mode 100644
index 0000000..0a5d1f7
--- /dev/null
+++ b/themes/etch/layouts/_default/baseof.html
@@ -0,0 +1,11 @@
+
+
+ {{- partial "head.html" . -}}
+
+ {{- partial "header.html" . -}}
+
+ {{- block "main" . }}{{- end }}
+
+ {{- partial "footer.html" . -}}
+
+
diff --git a/themes/etch/layouts/_default/li.html b/themes/etch/layouts/_default/li.html
new file mode 100644
index 0000000..f418cb9
--- /dev/null
+++ b/themes/etch/layouts/_default/li.html
@@ -0,0 +1,6 @@
+
+
+ {{ .Title }}
+ {{ .Date | time.Format (i18n "posts.date") }}
+
+
diff --git a/themes/etch/layouts/_default/list.html b/themes/etch/layouts/_default/list.html
new file mode 100644
index 0000000..97af0e3
--- /dev/null
+++ b/themes/etch/layouts/_default/list.html
@@ -0,0 +1,3 @@
+{{ define "main" }}
+{{- partial "posts.html" . -}}
+{{ end }}
diff --git a/themes/etch/layouts/_default/rss.xml b/themes/etch/layouts/_default/rss.xml
new file mode 100644
index 0000000..4accedd
--- /dev/null
+++ b/themes/etch/layouts/_default/rss.xml
@@ -0,0 +1,41 @@
+{{- $pctx := . -}}
+{{- if .IsHome -}}{{ $pctx = .Site }}{{- end -}}
+{{- $pages := slice -}}
+{{- if or $.IsHome $.IsSection -}}
+{{- $pages = $pctx.RegularPages -}}
+{{- else -}}
+{{- $pages = $pctx.Pages -}}
+{{- end -}}
+{{- $limit := .Site.Config.Services.RSS.Limit -}}
+{{- if ge $limit 1 -}}
+{{- $pages = $pages | first $limit -}}
+{{- end -}}
+{{- printf "" | safeHTML }}
+
+
+ {{ if eq .Title .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{.}} on {{ end }}{{ .Site.Title }}{{ end }}
+ {{ .Permalink }}
+ Recent content {{ if ne .Title .Site.Title }}{{ with .Title }}in {{.}} {{ end }}{{ end }}on {{ .Site.Title }}
+ Hugo -- gohugo.io {{ with .Site.LanguageCode }}
+ {{.}} {{end}}{{ with .Site.Author.email }}
+ {{.}}{{ with $.Site.Author.name }} ({{.}}){{end}} {{end}}{{ with .Site.Author.email }}
+ {{.}}{{ with $.Site.Author.name }} ({{.}}){{end}} {{end}}{{ with .Site.Copyright }}
+ {{.}} {{end}}{{ if not .Date.IsZero }}
+ {{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }} {{ end }}
+ {{ with .OutputFormats.Get "RSS" }}
+ {{ printf " " .Permalink .MediaType | safeHTML }}
+ {{ end }}
+ {{ range where .Site.Pages "Kind" "page" }}
+ {{ if or (eq .Section "posts") (eq .Section "post") }}
+ -
+
{{ .Title }}
+ {{ .Permalink }}
+ {{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}
+ {{ with .Site.Author.email }}{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}} {{end}}
+ {{ .Permalink }}
+ {{ .Content | html }}
+
+ {{ end }}
+ {{ end }}
+
+
diff --git a/themes/etch/layouts/_default/single.html b/themes/etch/layouts/_default/single.html
new file mode 100644
index 0000000..281e064
--- /dev/null
+++ b/themes/etch/layouts/_default/single.html
@@ -0,0 +1,17 @@
+{{ define "main" }}
+
+
+ {{- .Content -}}
+
+{{ end }}
diff --git a/themes/etch/layouts/_default/taxonomy.html b/themes/etch/layouts/_default/taxonomy.html
new file mode 100644
index 0000000..86677c2
--- /dev/null
+++ b/themes/etch/layouts/_default/taxonomy.html
@@ -0,0 +1,8 @@
+{{ define "main" }}
+{{ .Title }}
+
+{{- range .Pages }}
+ {{ .Render "li" }}
+{{- end }}
+
+{{ end }}
diff --git a/themes/etch/layouts/index.html b/themes/etch/layouts/index.html
new file mode 100644
index 0000000..b134404
--- /dev/null
+++ b/themes/etch/layouts/index.html
@@ -0,0 +1,4 @@
+{{ define "main" }}
+{{ .Content }}
+{{ partial "posts.html" . }}
+{{ end }}
diff --git a/themes/etch/layouts/partials/footer.html b/themes/etch/layouts/partials/footer.html
new file mode 100644
index 0000000..7071476
--- /dev/null
+++ b/themes/etch/layouts/partials/footer.html
@@ -0,0 +1,5 @@
+
diff --git a/themes/etch/layouts/partials/head.html b/themes/etch/layouts/partials/head.html
new file mode 100644
index 0000000..839d7ca
--- /dev/null
+++ b/themes/etch/layouts/partials/head.html
@@ -0,0 +1,34 @@
+
+
+
+ {{ with .Site.Params.description -}}
+
+ {{ end }}
+ {{ printf ` ` ("favicon.ico" | absURL) | safeHTML }}
+ {{ with .OutputFormats.Get "rss" -}}
+ {{ printf ` ` .Rel .MediaType.Type .Permalink $.Site.Title | safeHTML }}
+ {{ end -}}
+
+ {{ $resources := slice -}}
+
+ {{ $resources = $resources | append (resources.Get "css/main.css") -}}
+
+ {{ $resources = $resources | append (resources.Get "css/min770px.css") -}}
+
+ {{ $dark := .Site.Params.dark | default "auto" -}}
+ {{ if not (eq $dark "off") -}}
+ {{ $resources = $resources | append (resources.Get "css/dark.css" | resources.ExecuteAsTemplate "dark.css" .) -}}
+ {{ end -}}
+
+ {{ if .Site.Params.highlight -}}
+ {{ $resources = $resources | append (resources.Get "css/syntax.css") -}}
+ {{ end -}}
+
+ {{ $css := $resources | resources.Concat "css/style.css" | minify }}
+ {{ printf ` ` $css.RelPermalink | safeHTML }}
+
+
+
+
+ {{ .Title }}
+
diff --git a/themes/etch/layouts/partials/header.html b/themes/etch/layouts/partials/header.html
new file mode 100644
index 0000000..9a66449
--- /dev/null
+++ b/themes/etch/layouts/partials/header.html
@@ -0,0 +1,12 @@
+
+
+
+
+ {{ range .Site.Menus.main.ByWeight -}}
+
+ {{ .Pre }}{{- .Name -}} {{ .Post }}
+
+ {{- end }}
+
+
+
diff --git a/themes/etch/layouts/partials/posts.html b/themes/etch/layouts/partials/posts.html
new file mode 100644
index 0000000..5572a6c
--- /dev/null
+++ b/themes/etch/layouts/partials/posts.html
@@ -0,0 +1,5 @@
+
+{{- range where site.RegularPages "Type" "in" site.Params.mainSections }}
+ {{ .Render "li" }}
+{{- end }}
+
diff --git a/themes/etch/layouts/shortcodes/toc.html b/themes/etch/layouts/shortcodes/toc.html
new file mode 100644
index 0000000..22da6e7
--- /dev/null
+++ b/themes/etch/layouts/shortcodes/toc.html
@@ -0,0 +1,4 @@
+
+ Table of Contents
+ {{ .Page.TableOfContents }}
+
diff --git a/themes/etch/theme.toml b/themes/etch/theme.toml
new file mode 100644
index 0000000..07f201a
--- /dev/null
+++ b/themes/etch/theme.toml
@@ -0,0 +1,13 @@
+name = "Etch"
+license = "MIT"
+licenselink = "https://github.com/LukasJoswiak/etch/blob/master/LICENSE"
+description = "Lightweight Hugo theme with a focus on content"
+homepage = "https://github.com/LukasJoswiak/etch"
+demosite = "https://lukasjoswiak.github.io/etch/"
+tags = ["simple", "minimal", "clean", "fast", "blog", "responsive", "dark mode", "privacy"]
+features = ["fast", "blog", "syntax highlighting", "dark mode"]
+min_version = "0.41"
+
+[author]
+ name = "Lukas Joswiak"
+ homepage = "https://lukasjoswiak.com"