120 changes: 120 additions & 0 deletions css/global/_melange.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Melange palette is taken from https://github.com/savq/melange-nvim
// Light palette
$melange_light_a_bg: #f1f1f1;
$melange_light_a_float: #e9e1db;
$melange_light_a_sel: #d9d3ce;
$melange_light_a_ui: #a98a78;
$melange_light_a_com: #7d6658;
$melange_light_a_fg: #54433a;

$melange_light_b_red: #bf0021;
$melange_light_b_yellow: #a06d00;
$melange_light_b_green: #3a684a;
$melange_light_b_cyan: #3d6568;
$melange_light_b_blue: #465aa4;
$melange_light_b_magenta: #904180;

$melange_light_c_red: #c77b8b;
$melange_light_c_yellow: #bc5c00;
$melange_light_c_green: #6e9b72;
$melange_light_c_cyan: #739797;
$melange_light_c_blue: #7892bd;
$melange_light_c_magenta: #be79bb;

$melange_light_d_red: #f1dedf;
$melange_light_d_yellow: #cca478;
$melange_light_d_green: #d0e9d1;
$melange_light_d_cyan: #cde8e7;
$melange_light_d_blue: #e0e2e8;
$melange_light_d_magenta: #e8e0e8;

// Dark palette
$melange_dark_a_bg: #292522;
$melange_dark_a_float: #34302c;
$melange_dark_a_sel: #403a36;
$melange_dark_a_ui: #867462;
$melange_dark_a_com: #c1a78e;
$melange_dark_a_fg: #ece1d7;

$melange_dark_b_red: #d47766;
$melange_dark_b_yellow: #ebc06d;
$melange_dark_b_green: #85b695;
$melange_dark_b_cyan: #89b3b6;
$melange_dark_b_blue: #a3a9ce;

$melange_dark_b_magenta: #cf9bc2;
$melange_dark_c_red: #bd8183;
$melange_dark_c_yellow: #e49b5d;
$melange_dark_c_green: #78997a;
$melange_dark_c_cyan: #7b9695;
$melange_dark_c_blue: #7f91b2;
$melange_dark_c_magenta: #b380b0;

$melange_dark_d_red: #7d2a2f;
$melange_dark_d_yellow: #8b7449;
$melange_dark_d_green: #233524;
$melange_dark_d_cyan: #253333;
$melange_dark_d_blue: #273142;
$melange_dark_d_magenta: #422741;

:root {
--melange_a_bg: $melange_light_a_bg;
--melange_a_float: $melange_light_a_float;
--melange_a_sel: $melange_light_a_sel;
--melange_a_ui: $melange_light_a_ui;
--melange_a_com: $melange_light_a_com;
--melange_a_fg: $melange_light_a_fg;

--melange_b_red: $melange_light_b_red;
--melange_b_yellow: $melange_light_b_yellow;
--melange_b_green: $melange_light_b_green;
--melange_b_cyan: $melange_light_b_cyan;
--melange_b_blue: $melange_light_b_blue;
--melange_b_magenta: $melange_light_b_magenta;

--melange_c_red: $melange_light_c_red;
--melange_c_yellow: $melange_light_c_yellow;
--melange_c_green: $melange_light_c_green;
--melange_c_cyan: $melange_light_c_cyan;
--melange_c_blue: $melange_light_c_blue;
--melange_c_magenta: $melange_light_c_magenta;

--melange_d_red: $melange_light_d_red;
--melange_d_yellow: $melange_light_d_yellow;
--melange_d_green: $melange_light_d_green;
--melange_d_cyan: $melange_light_d_cyan;
--melange_d_blue: $melange_light_d_blue;
--melange_d_magenta: $melange_light_d_magenta;
}

@media (prefers-color-scheme: dark) {
:root {
--melange_a_bg: $melange_dark_a_bg;
--melange_a_float: $melange_dark_a_float;
--melange_a_sel: $melange_dark_a_sel;
--melange_a_ui: $melange_dark_a_ui;
--melange_a_com: $melange_dark_a_com;
--melange_a_fg: $melange_dark_a_fg;

--melange_b_red: $melange_dark_b_red;
--melange_b_yellow: $melange_dark_b_yellow;
--melange_b_green: $melange_dark_b_green;
--melange_b_cyan: $melange_dark_b_cyan;
--melange_b_blue: $melange_dark_b_blue;

--melange_b_magenta: $melange_dark_b_magenta;
--melange_c_red: $melange_dark_c_red;
--melange_c_yellow: $melange_dark_c_yellow;
--melange_c_green: $melange_dark_c_green;
--melange_c_cyan: $melange_dark_c_cyan;
--melange_c_blue: $melange_dark_c_blue;
--melange_c_magenta: $melange_dark_c_magenta;

--melange_d_red: $melange_dark_d_red;
--melange_d_yellow: $melange_dark_d_yellow;
--melange_d_green: $melange_dark_d_green;
--melange_d_cyan: $melange_dark_d_cyan;
--melange_d_blue: $melange_dark_d_blue;
--melange_d_magenta: $melange_dark_d_magenta;
}
}
274 changes: 240 additions & 34 deletions css/local/_post.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,46 +9,252 @@ article.article-content {
a {
word-wrap: break-word;
}
}

article.article-content > * + * {
margin-block-start: var(--space-xs);
}
& > * + * {
margin-block-start: var(--space-xs);
}

article.article-content figure {
@include overflow-bleed;
text-align: center;
figure {
@include overflow-bleed;
text-align: center;

figcaption {
font-style: italic;
figcaption {
font-style: italic;
max-inline-size: none;
}
}

h1,
h2,
h3,
h4,
h5,
h6 {
& > a:not(:first-of-type) {
text-decoration: underline;
}

&:not(:first-child) {
margin-block-start: var(--space-m);
}
}

/*
* Code
*/
pre,
code {
font-family: $code-font-family;
// Hack is quite a bit larger than the other fonts
// Should maybe use Triplicate instead?
font-size: 0.95rem;
// font-size: var(--font-size-s);
// max-inline-size: none;
}

pre code {
padding: 0;
width: 100%;
max-inline-size: none;
// --measure: 100ch;
}
pre.wide {
@include overflow-bleed;
}
pre {
max-inline-size: none;
// padding: 0.4em 0.6em;
padding: var(--space-xs);
// padding-top: var(--space-s);
overflow-wrap: normal;
overflow: auto;
}
code {
padding: 0.2rem;
margin: 0;
}
}

pre,
code {
font-family: $code-font-family;
// Hack is quite a bit larger than the other fonts
// Should maybe use Triplicate instead?
font-size: 0.95rem;
// font-size: var(--font-size-s);
// max-inline-size: none;
}
// mmh... This isn't very pretty I know.
pre {
pre::before {
float: right;
font-size: var(--font-size-s);
color: var(--melange_a_ui);
position: relative;
top: -0.5rem;
left: 0.1rem;
}
code.highlight.python::before {
content: "python";
}
code.highlight.fish::before {
content: "fish";
}
code.highlight.c::before {
content: "c";
}
code.highlight.bash::before {
content: "bash";
}
code.highlight.html::before {
content: "html";
}
code.highlight.js::before {
content: "js";
}
code.highlight.haskell::before {
content: "haskell";
}
code.highlight.pollen::before {
content: "pollen";
}
code.highlight.racket::before {
content: "racket";
}
code.highlight.json::before {
content: "json";
}
code.highlight.md::before {
content: "markdown";
}
code.highlight.css::before {
content: "css";
}
code.highlight.diff::before {
content: "diff";
}
code.highlight.lua::before {
content: "lua";
}
code.highlight.markdown::before {
content: "markdown";
}
code.highlight.ml::before {
content: "ml";
}
code.highlight.perl::before {
content: "perl";
}
code.highlight.ruby::before {
content: "ruby";
}
code.highlight.rust::before {
content: "rust";
}
code.highlight.scss::before {
content: "scss";
}
code.highlight.shell::before {
content: "shell";
}
code.highlight.vhdl::before {
content: "vhdl";
}
code.highlight.vim::before {
content: "vimscript";
}
code.highlight.xml::before {
content: "xml";
}
code.highlight.yaml::before {
content: "yaml";
}
}

pre code {
padding: 0;
width: 100%;
max-inline-size: none;
// --measure: 100ch;
}
pre {
@include overflow-bleed;
/*
* Quotes
*/
& blockquote {
font-size: 95%;
padding-inline-start: var(--space-m);
padding-block: var(--space-2xs);

padding: 0.4em 0.6em;
overflow-wrap: normal;
overflow: auto;
}
code {
padding: 0.2em;
margin: 0;
& > * + * {
margin-block-start: var(--space-xs);
}
}
& > blockquote {
border-left: 3px solid var(--color-text);
}
.epigraph {
margin-block: var(--space-l);
font-style: italic;
}
blockquote > footer {
font-size: 90%;
text-align: right;
}

/*
* Tables
*/
table {
@extend %serif;
// Need tabular numbers to align properly
font-feature-settings: "kern" on, "tnum" on;
}
th,
td {
padding: var(--space-3xs) var(--space-s) var(--space-3xs) 0;
}

// This is just for one single post
table.movie-table {
width: 100%;

td:first-of-type {
width: 25ch;
}
}
table.center {
margin: 0 auto;
}

/*
* Horizontal rules
*/
hr {
// Remove article based spacing
// FIXME should that be a variable?
margin: var(--space-m) 0 calc(var(--space-m) - var(--space-xs)) 0;
}

/*
* Lists
*/
$left: 2rem;

ul,
ol {
list-style: none;
margin: 1rem 0 1rem $left;
}
ol {
counter-reset: ordered-counter;
}
// Consistent spacing between items
ol > * + *,
ul > * + * {
margin-block-start: var(--space-xs);
}
// Consistent spacing inside items
li > * + * {
margin-block-start: var(--space-xs);
}
// Replace standard item bullets/numbers with our own
// and add in some spacing.
ol > li::before,
ul > li::before {
float: left;
margin-left: -$left;
}
ol > li::before {
@extend %sans-serif;
counter-increment: ordered-counter;
content: counter(ordered-counter);
}
ul > li::before {
@extend %sans-serif;
content: "•";
}
}
283 changes: 283 additions & 0 deletions drafts/mdtest.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
---
layout: post
title: md_test (h1)
tags: Gaming, Ludum Dare
---

> Mamma Mia! Here we go again...
> { :epigraph }
# Header 1 (h2)

Something

## Header 2 (h3)

Others

### Header 3 (h4)

In 3

#### Header 4 (h5)

In 4

#### Header 5 (h6)

In 5

# Just text

Consider having your front door locked for example. You could consider your home secure if your door is locked and insecure if it’s open but that doesn’t say what you’re secure against. It’s missing context. It might prevent opportunistic thefts but a more determined attacker could instead break a window, pick the lock of the door or simply break down the door itself. [Maybe you live in a neighborhood](#) with lots of thefts and you might want an alarm system, a dog or iron bars over your windows.

At the same time it might not be practical to go all out and get the best protection possible. You might not want to give up your life and move to a bunker where your friends can’t visit and a private security force may be slightly too expensive.

---

abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz

Unicode snowman: ☃︎ and "auto quotes" enabled. It's good. --dashes--? Converts... to …

Quotes are "cool". Or are they 'cool'? 1234567890


ff fi fj ffl

This text is **bold**. This is _italicized_. This is **_both_** `Here's some code.`.

[blog](/blog) and auto <https://google.com> email: <mail@jonashietala.se>

# Lists

Unordered list:

- Milk
- Bread
- Cheese

Paragraph

- Rice

Ordered list:

1. Milk
2. Bread
3. Cheese
4. Rice

Can also have some text here

And here

1. Another
2. Nested
3. List

5. Pew
This is really close
I think it's too close?

# Quotes and attributes

> This is an epigraph
{ :epigraph }

Text

> Just a normal quote. Where some dude says something smart.
> And the next line.
Nesting:

> First level of quoting.
>
> > This is a nested blockquote
>
> Hmm
> Back to the first level.
Text

> This is [a notice](#)
{ :notice }

Text

> With author attribution
{ author=John Doe }


# Tables

Table:

| Left aligned | Centered | Right aligned |
| :----------- | :--------: | ------------: |
| First row | Data | Data |
| Second row | **Cell** 1 | 1111 |
| Third row | **Cell** 2 | 3333 |
| Fourth row | **Cell** 3 | 6789 |

Easy table So cool

| One | Two |
| --- | --- |
| 1 | 2 |
{ .class }

Movie | Rank this year | Rank last year | change
:----- | -------------- | -------------- | ------
Avengers: Endgame | 1 | - | -
Guardians of the Galaxy | 2 | 5 | +3
Avengers: Infinity War | 3 | 4 | +1
Iron Man | 4 | 1 | -3
Captain America: The Winter Soldier | 5 | 3 | -2
{ .movie-table }

Movie | Rank this year | Rank last year | change
:----- | -------------- | -------------- | ------
The Incredible Hulk | 21 | 19 | -2
Thor 2: The Dark World | 22 | 17 | -5
{ .movie-table }

# Code

So we should do `foo` then `bar` then `quux`

```fish
python3 -m pygments -l pollen.py:PollenLexer -x -f html pollen.html.pm
```

```css
/* Gruvbox inspired */
code,
pre {
background-color: #f2e5bc;
}
code.sourceCode span.kw {
color: #9d0006;
} /* Keyword red */
code.sourceCode span.dt {
color: #b57614;
} /* Datatype yellow */
code.sourceCode span.dv {
color: #8f3f71;
} /* DecVal purple */
code.sourceCode span.bn {
color: #8f3f71;
} /* BaseN purple */
code.sourceCode span.fl {
color: #8f3f71;
} /* Float purple */
code.sourceCode span.ch {
color: #4070a0;
} /* Char purple */
code.sourceCode span.st {
color: #79740e;
} /* String green */
code.sourceCode span.co {
color: #928374;
font-style: italic;
}
code.sourceCode span.ot {
color: #427b56;
} /* OtherToken aqua */
code.sourceCode span.fu {
color: #79740e;
} /* Function green */
```

```css
@font-face {
font-family: "Source Code";
src: url("/fonts/SourceCodeVariable-Roman.woff") format("woff"); /* 80 ch */
src: url("/fonts/SourceCodeVariable-Roman.woff") format("woff"); /*------ 90 ch ----*/
src: url("/fonts/SourceCodeVariable-Roman.woff") format("woff"); /*---------- 100 ch ---------*/
src: url("/fonts/SourceCodeVariable-Roman.woff") format("woff"); /*------------------ 120 ch ------------------------*/
}
```

```C
#pragma once
#include "foo.h"

/* Awesome function */
int main(int *argc, int *argv[]) {
for (int i = 1; i < argc; ++i) {
printf("%s\n", argv[i]);
}

float x = 1.3;
char *my_string = ['a', 'b', '\n', '\0'];

/*
**x int = 42;
*/
#if x
char *action = "foo";
#else
char *action = "quux";
#endif

/* I has fold?: {{{ */
int **pp = 0;
/* }}} */
//BEGIN
/* Here be region marker
TODO use this to make good stuff
*/
typedef struct {
int i;
char k;
} elem_t;
elem_t user;
//END
#badsyntax

<= => !==

// This is a very quite a long line really: asd asd asd asd asdasd asd asd asdasd asd as asd asd asd asdasd asd asd asd asd ads asd asd asd asd asd asd asd asd asd asd asd asd asd asd asd asdasd asd

/* multiline
* comment
*/
}
```
# Images
Figure:
![FTL is such an amazing game](/images/ftl_start.png)
Set properties:
![A small led cube displayed in 400px](/images/small_led_cube.jpg){ width=400px }
Flex images
::: Flex
/images/configura14/octree1.png
/images/configura14/octree2.png
:::
Image gallery:
::: Gallery
/images/inside1.jpg
/images/case.jpg
/images/cables.jpg
/images/inside2.jpg
/images/das1.jpg
:::
End gallery. Ooh so pretty! :)
# Embed YouTube
http://www.youtube.com/watch?v=eoKDyhxCVm0
# Sidenotes
136 changes: 68 additions & 68 deletions drafts/rewriting_my_neovim_config_in_lua.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -212,117 +212,117 @@ While doing the rewrite I went through my existing plugins to see if they were s

I won't create a list of my favorite plugins, as it would be boring to see yet another list with [LSP][lspconfig], [treesitter][nvim-treesitter] and [cmp][nvim-cmp], I'll instead highlight some good plugins that were new to me:

- [lazy.nvim][]: A modern plugin manager
## [lazy.nvim][]: A modern plugin manager

![Observe the glory of a modern package manager](/images/rewrite_neovim_lua/lazy.png)
![Observe the glory of a modern package manager](/images/rewrite_neovim_lua/lazy.png)

I've been using [vim-plug][] as my plugin manager since forever. It's been working well, but I figured I should try one of these newer managers to see if I was missing something. And boy, did I. [lazy.nvim][] has some really nice features that I now can't live without:
I've been using [vim-plug][] as my plugin manager since forever. It's been working well, but I figured I should try one of these newer managers to see if I was missing something. And boy, did I. [lazy.nvim][] has some really nice features that I now can't live without:

- Split plugin specifications in separate files as I wrote about [earlier in the post](#structured-configuration).
- Specify plugin dependencies.
- Pin plugin versions.
- Track plugin versions in `lazy-lock.json`, so you can identify what plugin version breaks your setup so you can pin it to a known good version.
- Lazy loading. It's nice to have for those rarely used but heavy plugins.
- Split plugin specifications in separate files as I wrote about [earlier in the post](#structured-configuration).
- Specify plugin dependencies.
- Pin plugin versions.
- Track plugin versions in `lazy-lock.json`, so you can identify what plugin version breaks your setup so you can pin it to a known good version.
- Lazy loading. It's nice to have for those rarely used but heavy plugins.

- [melange-nvim][]: An amazing colorscheme
## [melange-nvim][]: An amazing colorscheme

![It's just pleasing to my eyes.](/images/rewrite_neovim_lua/melange2.png)
![It's just pleasing to my eyes.](/images/rewrite_neovim_lua/melange2.png)

![The design idea is that control flow should use warm colors and data should use cold colors.
So here, functions are warm yellow and strings and data are colder purple and green.](/images/rewrite_neovim_lua/melange3.png)
![The design idea is that control flow should use warm colors and data should use cold colors.
So here, functions are warm yellow and strings and data are colder purple and green.](/images/rewrite_neovim_lua/melange3.png)

I've been a gruvbox user since I started using Vim almost 15 years ago. I've tried tons of different colorschemes but nothing has ever come close to gruvbox for me. Most of the popular colorschemes are just too blue, or have too little (or too much) contrast or I just don't like them for some random reason.
I've been a gruvbox user since I started using Vim almost 15 years ago. I've tried tons of different colorschemes but nothing has ever come close to gruvbox for me. Most of the popular colorschemes are just too blue, or have too little (or too much) contrast or I just don't like them for some random reason.

I had almost resigned to becoming a gruvbox-lifer, unable to ever change colorscheme.
I had almost resigned to becoming a gruvbox-lifer, unable to ever change colorscheme.

And then, [melange-nvim][] appeared. And it's glorious!
Now after many long years, I've finally switched to a new colorscheme, and I'm content.
And then, [melange-nvim][] appeared. And it's glorious!
Now after many long years, I've finally switched to a new colorscheme, and I'm content.

(No, switching from the original [gruvbox][] to [gruvbox.nvim][] to [gruvbox-material][] and back again doesn't count.)
(No, switching from the original [gruvbox][] to [gruvbox.nvim][] to [gruvbox-material][] and back again doesn't count.)

Also a shout-out to [kanagawa][] (dragon, the dark variant without blue background) which is the only colorscheme I've found that I didn't eject in horror after 5 minutes, except for gruvbox and melange.
Also a shout-out to [kanagawa][] (dragon, the dark variant without blue background) which is the only colorscheme I've found that I didn't eject in horror after 5 minutes, except for gruvbox and melange.

![Sorry [kanagawa][]. It's not you, it's me.](/images/rewrite_neovim_lua/kanagawa.png)
![Sorry [kanagawa][]. It's not you, it's me.](/images/rewrite_neovim_lua/kanagawa.png)

- [vim-cool][]: Turn off search highlight
## [vim-cool][]: Turn off search highlight

Forget `<C-l>`, this plugin will turn off search highlight when you move your cursor away from it.
Simple, but raises the quality of life a *lot*.
Forget `<C-l>`, this plugin will turn off search highlight when you move your cursor away from it.
Simple, but raises the quality of life a *lot*.

- [conform][]: Format on save
## [conform][]: Format on save

I've used [neoformat][] before, but had some issues where I saved then quickly stared modifying something, but then formating kicked in and removed my changes.
I've used [neoformat][] before, but had some issues where I saved then quickly stared modifying something, but then formating kicked in and removed my changes.

With [conform][] I haven't had these issues, and configuration was quick and easy and LSP fallback is super sweet. Excellent plugin.
With [conform][] I haven't had these issues, and configuration was quick and easy and LSP fallback is super sweet. Excellent plugin.

- [nvim-treesitter-textobjects][]
## [nvim-treesitter-textobjects][]

A common misconception about treesitter is that it only adds semantics to syntax highlighting:
A common misconception about treesitter is that it only adds semantics to syntax highlighting:

![BASE and REPEAT are enum members, while the other keycodes are defined as macros.](/images/rewrite_neovim_lua/base_layout.png)
![BASE and REPEAT are enum members, while the other keycodes are defined as macros.](/images/rewrite_neovim_lua/base_layout.png)

I think that's very nice, but treesitter is more than that. And a great example of that is [nvim-treesitter-textobjects][] where you can operate on treesitter nodes. I have for example:
I think that's very nice, but treesitter is more than that. And a great example of that is [nvim-treesitter-textobjects][] where you can operate on treesitter nodes. I have for example:

- `]f` jump to next function.
- `]c` jump to next class.
- `]g` jump to next function or class.
- `<leader>s` swap next parameter.
- `if` textobject for inner function. So `cif` would delete the function body and enter insert mode.
- `ax` textobject for outer comment, to easily delete/change comments.
- `]f` jump to next function.
- `]c` jump to next class.
- `]g` jump to next function or class.
- `<leader>s` swap next parameter.
- `if` textobject for inner function. So `cif` would delete the function body and enter insert mode.
- `ax` textobject for outer comment, to easily delete/change comments.

The beauty is that these work on treesitter nodes, so they work equally well across languages for functions like `fn myfun() { }`rust, `function myfun() ... end`lua or a `def myfun() do ... end`elixir. (Given that the treesitter implementation supports these options. Markdown doesn't have the concept of a function for instance.)
The beauty is that these work on treesitter nodes, so they work equally well across languages for functions like `fn myfun() { }`rust, `function myfun() ... end`lua or a `def myfun() do ... end`elixir. (Given that the treesitter implementation supports these options. Markdown doesn't have the concept of a function for instance.)

- [neogit][]: Git management
## [neogit][]: Git management

[magit][] is widely regarded as the best Git client/integration there is.
When I used Emacs for work (oh yes, the horrors) I did use [magit][] and yes it was great (although too slow on Windows).
[magit][] is widely regarded as the best Git client/integration there is.
When I used Emacs for work (oh yes, the horrors) I did use [magit][] and yes it was great (although too slow on Windows).

I don't think I need to say more than that [Neogit][] is [magit][], but for Neovim, and it is also great.
(It doesn't have feature parity with [magit][] yet, but it's good enough to have replaced [fugitive][] for me.)
I don't think I need to say more than that [Neogit][] is [magit][], but for Neovim, and it is also great.
(It doesn't have feature parity with [magit][] yet, but it's good enough to have replaced [fugitive][] for me.)

- [alpha-nvim][]: Dashboard
## [alpha-nvim][]: Dashboard

![My startup screen](/images/rewrite_neovim_lua/alpha.png)
![My startup screen](/images/rewrite_neovim_lua/alpha.png)

I'm going to be honest here: I've always thought that a dashboard was unnecessary fluff and people who used them were just pimping Neovim for the sake of pimping.
I'm going to be honest here: I've always thought that a dashboard was unnecessary fluff and people who used them were just pimping Neovim for the sake of pimping.

And now, I also use a dashboard.
And now, I also use a dashboard.

While it's something I could absolutely live without, by now I'd rather have it than not.
While it's something I could absolutely live without, by now I'd rather have it than not.

Okay, saving a keypress by using `f` instead `<leader>f` isn't a big deal.
And yeah, showing [lazy.nvim][] stats is probably unnecessary.
Okay, saving a keypress by using `f` instead `<leader>f` isn't a big deal.
And yeah, showing [lazy.nvim][] stats is probably unnecessary.

But having a list of keymaps that I should internalize is actually really nice.
It helps remind me of these cool new keymaps I've added, so they don't get forgotten for years until my next config rewrite.
But having a list of keymaps that I should internalize is actually really nice.
It helps remind me of these cool new keymaps I've added, so they don't get forgotten for years until my next config rewrite.

Yes, the list of keymaps is currently just hardcoded in the dashboard config.
But I would like to implement keymap tracking and use it for spaced repetition.
Maybe even have a floating window on startup that you need to clear every day, similar to "flashcards".
This is a nice idea for a plugin that I may or may not write in the future...
Yes, the list of keymaps is currently just hardcoded in the dashboard config.
But I would like to implement keymap tracking and use it for spaced repetition.
Maybe even have a floating window on startup that you need to clear every day, similar to "flashcards".
This is a nice idea for a plugin that I may or may not write in the future...

- [flash.nvim][]: Navigational plugin
## [flash.nvim][]: Navigational plugin

Once upon a time there was [vim-sneak][] that added the motion `s` to jump to any location by specifying two characters.
It was great, and it spawned a slew of other similar plugins that expanded on the idea.
(I'm not sure this is completely historically accurate, but it felt like a good narrative.)
Once upon a time there was [vim-sneak][] that added the motion `s` to jump to any location by specifying two characters.
It was great, and it spawned a slew of other similar plugins that expanded on the idea.
(I'm not sure this is completely historically accurate, but it felt like a good narrative.)

The plugin I've landed on is [flash.nvim][].
What I really like about it is the idea of typing as many characters as possible.
Even with sneak I didn't always arrive where I wanted, so having the option of typing out more things felt good for me.
The plugin I've landed on is [flash.nvim][].
What I really like about it is the idea of typing as many characters as possible.
Even with sneak I didn't always arrive where I wanted, so having the option of typing out more things felt good for me.

Extra functionality such as doing a "remote yank" (search, yank something, then cursor goes back to where it was) and enhancing `f`/`F`/`t`/`T`/`/` is just gravy.
Extra functionality such as doing a "remote yank" (search, yank something, then cursor goes back to where it was) and enhancing `f`/`F`/`t`/`T`/`/` is just gravy.

- [nvim-colorizer][]: Colorizer plugin
## [nvim-colorizer][]: Colorizer plugin

![What are these colors again? It's the palette of [melange-nvim][] of course!](/images/rewrite_neovim_lua/colorizer.png)
![What are these colors again? It's the palette of [melange-nvim][] of course!](/images/rewrite_neovim_lua/colorizer.png)

After [vim-hexokinase][] got archived I had a minor panic.
It was a neat little plugin that highlighted colors inline, but without altering the highlight of the colors themselves, which is what all the other colorizer plugins seemed to do.
After [vim-hexokinase][] got archived I had a minor panic.
It was a neat little plugin that highlighted colors inline, but without altering the highlight of the colors themselves, which is what all the other colorizer plugins seemed to do.

Luckily I found [nvim-colorizer][] that does the same, and without having to build an external binary like hexokinase that always managed to break for some weird reason.
Luckily I found [nvim-colorizer][] that does the same, and without having to build an external binary like hexokinase that always managed to break for some weird reason.

I love when things just work.
I love when things just work.


# Custom behavior
Expand Down
39 changes: 20 additions & 19 deletions posts/2020-04-30-writing_a_pollen_lexer_in_pygments.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ The simpest [Pygments][] lexer might look like this:

[Pygments]: https://pygments.org/

```python3
```python
from pygments.lexer import *
from pygments.token import *
import re
Expand Down Expand Up @@ -74,7 +74,7 @@ Regular text â—Š; Trailing comment

Which should be pretty straightforward. We just need to add a single clause to the root state that matches everything from `â—Š;` to the end of the line:

```python3
```python
tokens = {
'root': [
(r'â—Š;.*?$', Comment),
Expand All @@ -88,7 +88,8 @@ python3 -m pygments -l pollen2.py:PollenLexer -x -f html pollen.html.pm
```

```html
<div class="highlight"><pre><span></span><span class="c">â—Š; Standard comment</span>
<div class="highlight"><pre><span></span>
<span class="c">â—Š; Standard comment</span>
Regular text <span class="c">â—Š; Trailing comment</span>
</pre></div>
```
Expand All @@ -106,7 +107,7 @@ Let's move on to embedding variables via `â—Š|var|`.

A first attempt could be like this:

```python3
```python
'root': [
(r'(â—Š\|)(\w+)(\|)',
bygroups(Name.Variable.Magic, Name.Variable, Name.Variable.Magic)),
Expand All @@ -123,27 +124,27 @@ This works, but there are two changes I'd like to make. The immediate problem is

If we look at the [existing Racket lexer][racket-lexer] they have defined a variable like this:

```python3
```python
valid_symbol_chars = r'[\w!$%*+,<=>?/.\'@&#:-]'
variable = r'[A-Z]%s*' % valid_symbol_chars
```

Which we can steal and copy to our class and use when we build our regex:

```python3
```python
(r'(â—Š\|)(%s)(\|)' % variable,
bygroups(Name.Variable.Magic, Name.Variable, Name.Variable.Magic)),
```

To make this work out of the box we also need to add the regex flags:

```python3
```python
flags = re.IGNORECASE | re.MULTILINE
```

The other thing I want to do is introduce another state. It's not strictly needed in this case, but as `â—Š` can be followed by different cases it makes the lexer easier to follow. Like this:

```python3
```python
'root': [
(r'â—Š;.*?$', Comment),
('â—Š', Name.Variable.Magic, 'post-magic'),
Expand Down Expand Up @@ -176,13 +177,13 @@ I thought this was going to be really hard, but Pygments supports this in variou

First the import:

```python3
```python
from pygments.lexers.lisp import RacketLexer
```

And the case is simply:

```python3
```python
'post-magic': [
...
(r'(\()(.+)(\))',
Expand All @@ -192,11 +193,11 @@ And the case is simply:
'#pop')
```

The interesting line is `using(RacketLexer, state='unquoted-datum')`python3 which delegates the lexer to `RacketLexer`, starting in state `unquoted-datum`. How did I figure out which initial state to start in? I tried to [read the code][racket-lexer] and make an educated guess...
The interesting line is `using(RacketLexer, state='unquoted-datum')`python which delegates the lexer to `RacketLexer`, starting in state `unquoted-datum`. How did I figure out which initial state to start in? I tried to [read the code][racket-lexer] and make an educated guess...

But we also need to ensure we use the regex flag of allowing the dot to match newlines as well, otherwise we won't match multiline racket expressions:

```python3
```python
flags = re.IGNORECASE | re.DOTALL | re.MULTILINE
```

Expand All @@ -213,39 +214,39 @@ First let's support the simpler `â—Švar{text args}` case.

Matching `â—Švar` is straightforward:

```python3
```python
'post-magic': [
...
(r'%s' % variable, Name.Variable, ('#pop', 'curly-start')),
],
```

We could do more here, but we're preparing for the future where we can also match against an optional `[...]` after the variable, so we'll delegate to another state. `('#pop', 'curly-start')`python3 essentially means we'll replace the current state `post-magic` with the new `curly-start` state.
We could do more here, but we're preparing for the future where we can also match against an optional `[...]` after the variable, so we'll delegate to another state. `('#pop', 'curly-start')`python essentially means we'll replace the current state `post-magic` with the new `curly-start` state.

```python3
```python
'curly-start': [
(r'\{', Name.Variable.Magic, ('#pop', 'curly-end'))
],
```

Here again we could've done more, but we want to be able to do recursive matching inside `{ ... }` as well. This is what the `curly-end` state does:

```python3
```python
'curly-end': [
(r'\}', Name.Variable.Magic, '#pop'),
include('root'),
],
```

`include('root')`python3 does what you might expect it to do: it copies all cases from our `root` state into the `curly-end` sate. This to avoid code duplication.
`include('root')`python does what you might expect it to do: it copies all cases from our `root` state into the `curly-end` sate. This to avoid code duplication.

And this can indeed highlight `â—Švar{ ... }` recursively!

![](/images/pollen_rework/var_rec.png)

To support an optional `[ ... ]` we can add another state before `curly-end` that either matches against square brackets or curly brackets:

```python3
```python
'post-magic': [
...
(r'%s' % variable, Name.Variable, ('#pop', 'post-var')),
Expand Down Expand Up @@ -276,7 +277,7 @@ Putting it all together we can now highlight the code we looked at in the start

And this is the complete lexer:

```python3
```python
from pygments.lexer import *
from pygments.token import *
from pygments.lexers.lisp import RacketLexer
Expand Down
45 changes: 42 additions & 3 deletions src/markdown/syntax_highlight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use syntect::{
parsing::SyntaxSet, util::LinesWithEndings,
};
use tracing::info;
use tracing::warn;

lazy_static! {
static ref SS: SyntaxSet = syntax_set();
Expand Down Expand Up @@ -75,7 +74,8 @@ fn push_code_highlight<S: AsRef<str>>(s: &mut String, lang: Option<S>, code: &st
}
Err(err) => {
// FIXME when we have highlighting for all languages, make this a panic.
warn!("Syntax highlight error: {}", err);
// warn!("Syntax highlight error: {}", err);
panic!("Syntax highlight error: {}", err);
}
}
};
Expand All @@ -85,6 +85,20 @@ fn push_code_highlight<S: AsRef<str>>(s: &mut String, lang: Option<S>, code: &st
s.push_str("</code>");
}

fn extra_code_class(s: &str) -> Option<&'static str> {
let count = largest_line_count(s);

if count > 66 {
Some("wide")
} else {
None
}
}

fn largest_line_count(s: &str) -> usize {
s.lines().map(|x| x.chars().count()).max().unwrap_or(0)
}

fn highlight(spec: &HighlightSpec, code: &str) -> Result<String> {
lazy_static! {
static ref SPAN_WRAPPER: Regex = Regex::new(r"^<span [^>]+>(?s)(.+)</span>$").unwrap();
Expand Down Expand Up @@ -163,7 +177,17 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlockSyntaxHighlight<'a
}

let mut res = String::new();
res.push_str("<pre>");

match extra_code_class(&code) {
Some(class) => {
res.push_str(r#"<pre class=""#);
res.push_str(class);
res.push_str(r#"">"#);
}
None => {
res.push_str("<pre>");
}
}
push_code_highlight(&mut res, lang, &code);
res.push_str("</pre>");

Expand Down Expand Up @@ -317,4 +341,19 @@ let square x = x * x
let res = convert(s);
assert_eq!(res.trim_end(), "<p>Inline <code>xxx</code> no lang</p>");
}

#[test]
fn test_extra_code_class() {
assert_eq!(largest_line_count("one\ntwo\nthree"), 5);
assert_eq!(extra_code_class("one\ntwo\nthree"), None);
assert_eq!(
extra_code_class(
r"
One line that is exactly 61... Which line, it's this one!!!!!
This is just a small line
"
),
Some("wide")
);
}
}
2 changes: 1 addition & 1 deletion src/markdown/table_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for TableAttrs<'a, I> {
// | One | Two
// | -- | --
// | 1 | 2
// { .class }";
// { .class }
//
// Will create events like:
// Start table
Expand Down