From 331195b0d690d89d43e7eca9565ea2b013e87f25 Mon Sep 17 00:00:00 2001 From: Miguel Date: Sun, 17 Mar 2019 13:34:44 +0100 Subject: many things --- 080_blog/00015_Admin/00050_Wine-in-LXC/index.md | 197 ++++++++++++++++++ .../00038_Theory/00010_Totient-Function/index.md | 16 -- 080_blog/00038_Theory/index.md | 0 .../00010_Links-and-Literature/index.md | 17 ++ .../00010_Links-and-Notes-and-Literature/index.md | 69 ------- 080_blog/00040_Haskell/00020_GHC-Notes/index.md | 39 ++++ .../00030_Xmonad-contribution/index.md | 20 ++ .../00040_Haskell/00065_Base64-Encoder/base64.cast | 220 +++++++-------------- .../00040_Haskell/00065_Base64-Encoder/index.md | 11 +- .../00130_Calculator-on-Parsec-and-GTK/calc.png | Bin 0 -> 30318 bytes .../00130_Calculator-on-Parsec-and-GTK/index.md | 16 +- .../00140_Minimalistic-SVG-Generator/index.md | 24 +-- .../00150_Applicative-vs-Monadic-Parsing/index.md | 176 ++++++++++++++++- .../00_pandoc_colors/index.md | 20 ++ .../00_pandoc_colors/index_breezedark.html | 117 +++++++++++ .../00_pandoc_colors/index_espresso.html | 113 +++++++++++ .../00_pandoc_colors/index_haddock.html | 109 ++++++++++ .../00_pandoc_colors/index_kate.html | 117 +++++++++++ .../00_pandoc_colors/index_monochrome.html | 96 +++++++++ .../00_pandoc_colors/index_pygments.html | 114 +++++++++++ .../00_pandoc_colors/index_tango.html | 113 +++++++++++ .../00_pandoc_colors/index_zenburn.html | 113 +++++++++++ .../00200_Estatico-Page-Maker/index.md | 23 ++- .../index.md | 1 + 080_blog/00040_Hex-Converter/hexman.html | 170 ++++++++++++++++ 080_blog/00040_Hex-Converter/index.md | 5 + .../00100_Webkit-Keyboardless-Navigation/index.md | 5 +- 080_blog/00110_Fool-Operating-System/index.md | 10 +- 28 files changed, 1648 insertions(+), 283 deletions(-) create mode 100644 080_blog/00015_Admin/00050_Wine-in-LXC/index.md delete mode 100644 080_blog/00038_Theory/00010_Totient-Function/index.md delete mode 100644 080_blog/00038_Theory/index.md create mode 100644 080_blog/00040_Haskell/00010_Links-and-Literature/index.md delete mode 100644 080_blog/00040_Haskell/00010_Links-and-Notes-and-Literature/index.md create mode 100644 080_blog/00040_Haskell/00020_GHC-Notes/index.md create mode 100644 080_blog/00040_Haskell/00030_Xmonad-contribution/index.md create mode 100644 080_blog/00040_Haskell/00130_Calculator-on-Parsec-and-GTK/calc.png create mode 100644 080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index.md create mode 100644 080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_breezedark.html create mode 100644 080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_espresso.html create mode 100644 080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_haddock.html create mode 100644 080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_kate.html create mode 100644 080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_monochrome.html create mode 100644 080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_pygments.html create mode 100644 080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_tango.html create mode 100644 080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_zenburn.html create mode 100644 080_blog/00040_Haskell/00_00150_Applicative-vs-Monadic-Parsing/index.md create mode 100644 080_blog/00040_Hex-Converter/hexman.html create mode 100644 080_blog/00040_Hex-Converter/index.md (limited to '080_blog') diff --git a/080_blog/00015_Admin/00050_Wine-in-LXC/index.md b/080_blog/00015_Admin/00050_Wine-in-LXC/index.md new file mode 100644 index 0000000..24344e0 --- /dev/null +++ b/080_blog/00015_Admin/00050_Wine-in-LXC/index.md @@ -0,0 +1,197 @@ +Wine inside LXC +=============== + +Abstract +-------- + +Running Wine inside an unpriviliged LXC Container as a secondary user, +utilizing the host systems OpenGL 3D acceleration and PulseAudio. + +Host System +----------- + +* Debian 9 / Stretch +* Xorg running as primary user "miguel" +* NVIDIA proprietary drivers (debian's contrib/non-free) +* PulseAudio up & running as primary user (I run pavucontrol as miguel) +* A Secondary user "retard2" with uid/gid=1002 + +Preparations +------------ + +Allow access to the display server and audio. Note that you should +restrict this in a real world setup (e.g. auth-ip-acl): + + migue@host$ xhost + # allow remote X access + +add this lines to /etc/pulse/default.pa and restart pulsaudio: + + load-module module-native-protocol-tcp auth-anonymous=1 + load-module module-zeroconf-publish + +Create Container +---------------- + + 1. In order to allow the creation of virutal network bridges as our + secondary user, add the following two lines to /etc/lxc/lxc-usernet: + + retard2 veth virbr0 2 + retard2 veth lxcbr0 10 + + 2. Login as retard2 ("su" does not work well with cgroups) + + miguel@host$ sudo machinectl login # than login as retard2 + retard2@host$ cat /proc/self/cgroup # just check cgroups if you want + + 3. Add subuid subgid mappings to /home/retard2/.config/lxc/default.conf + You can check the ranges in /etc/subuid and /etc/subgid: + + lxc.id_map = u 0 1541792 65536 + lxc.id_map = g 0 1541792 65536 + + 4. We are ready to create the lxc container as retard2: + + retard2@host$ lxc-create -n winebox -t download + + Select exactly the same distro / version / arch as you run on the + host. i.e. debian / stretch / amd64 + + retard2@host$ lxc-ls # assure that "winebox" LXC was created + + 5. Adapt the new config in: ~/.local/share/lxc/winebox/config adding: + + # NET + lxc.network.type = veth + lxc.network.link = lxcbr0 + lxc.network.flags = up + lxc.network.hwaddr = 00:16:3e:be:3c:5a + + # X + lxc.mount.entry = /dev/dri dev/dri none bind,create=dir + lxc.mount.entry = /tmp/.X11-unix tmp/.X11-unix none bind,create=dir + + # NVIDIA + lxc.mount.entry = /dev/nvidia0 dev/nvidia0 none bind,create=file + lxc.mount.entry = /dev/nvidiactl dev/nvidiactl none bind,create=file + + 6. Finally start the container and enter its realm: + + retard2@host$ lxc-start -n winebox + retard2@host$ lxc-ls --running # check it is up & running + retard2@host$ lxc-attach -n winebox -- su # enter container (as root) + +Inside the Container +-------------------- + + 1. Adapt /etc/apt/sources.list to make use of "contrib" and "non-free" + and run: + + root@winebox$ apt update + + 2. Get OpenGL running + + root@winebox$ apt upgrade + root@winebox$ apt install mesa-utils + root@winebox$ apt install xserver-xorg-video-nvidia + root@winebox$ DISPLAY=:0 glxgears # check + root@winebox$ DISPLAY=:0 glxinfo | grep "direct render" # check + + 3. Get PulseAudio running. + Please adapt the IP to the host's lxcbr0 ip address. + + root@winebox$ apt install pavucontrol + root@winebox$ DISPLAY=:0 PULSE_SERVER=10.0.5.1 pavucontrol + + At this point we should have accelerated video and audio running from + inside our LXC. Well Done! + +Wine +---- + +A few trivial requirements: + + root@winebox$ apt install wget + root@winebox$ apt install gnupg + root@winebox$ apt install apt-transport-https + +Now let's get some wine accoring to: https://wiki.winehq.org/Debian: + + root@winebox$ sudo dpkg --add-architecture i386 + root@winebox$ wget -nc https://dl.winehq.org/wine-builds/Release.key + root@winebox$ sudo apt-key add Release.key + +Add the debian stretch wine repo to your /etc/apt/sources.list: + + deb https://dl.winehq.org/wine-builds/debian/ stretch main + + root@winebox$ apt update + root@winebox$ apt-get install --install-recommends winehq-stable + +Unfortunatelly wine still depends on the 32-bit versions of some libs so +we have to replace our 64-bit verions by running: + + root@winebox$ apt install libgl1-nvidia-glx:i386 + +Restrict Networking +------------------- + +Now You can optionally restrict any communication with the outside world: + + miguel@host$ sudo iptables -F FORWARD #block traffic + miguel@host$ sudo iptables -P FORWARD DROP #block traffic + +If your host is forwarding traffic you will need to set up some rules. + +Finalizing Contianer +-------------------- + + 1. Create a non-root user: + root@winebox$ adduser lxc-retard + + 2. Now we can exit the container with : + root@winebox$ exit + + 3. Stop the container on the host. This might take some while. + retard2@host$ lxc-stop -n winebox + + 4. THIS WOULD BE A VERY GOOD MOMENT TO SNAPSHOT THE CONTIANER + FOR LATER REUSE! + +Summary +------- + +Congratulations! Now you are running "wine" as an unprivileged user +inside of an unprivileged container of a secondary user, utlizing your +hosts hardware acceleration and PulseAudio capabilities. + +Optionally traffic forwarding has been blocked, for increased security. + +Using the Container +------------------- + +To use your new container you will need to go through the following +steps each time: + + miguel@host$ xhost + + miguel@host$ sudo iptables -F FORWARD #block traffic + miguel@host$ sudo iptables -P FORWARD DROP #block traffic + miguel$host$ sudo machinectl login # and login as retard2 + + retard2@host$ lxc-start -n winebox + +Now you can attach to the container as lxc-retard user: + + retard2@host$ lxc-attach -n winebox -- su lxc-retard + +Alternatively we can attach as root: + + retard2@host$ lxc-attach -n winebox -- su + +Do not forget to stop container once you are finished: + + retard2@host$ lxc-stop -n winebox + +Remember that stopping might take a while. Be patient! + +Make sure to automate/adapt the process, according to your personal +preferences and requirements. diff --git a/080_blog/00038_Theory/00010_Totient-Function/index.md b/080_blog/00038_Theory/00010_Totient-Function/index.md deleted file mode 100644 index eea75f4..0000000 --- a/080_blog/00038_Theory/00010_Totient-Function/index.md +++ /dev/null @@ -1,16 +0,0 @@ -# Euler's totient function - -And now something completely different. Straight from the World of Number Theory. -Frankly, I just wanted to show off the powers of my new Estatico functionality -and give tribute to my all time hero **Leonhard Euler**. - -## Definition - -For a given value _n_ this function returns the number of positive integers, -relatively prime to _n_ up to _n_. - -## Computing - -You can compute it for instance via _Euler's product formula_, multiplying -over the distinct prime numbers dividing _p_: -$$\varphi(n) =n \prod_{p\mid n} \left(1-\frac{1}{p}\right)$$ diff --git a/080_blog/00038_Theory/index.md b/080_blog/00038_Theory/index.md deleted file mode 100644 index e69de29..0000000 diff --git a/080_blog/00040_Haskell/00010_Links-and-Literature/index.md b/080_blog/00040_Haskell/00010_Links-and-Literature/index.md new file mode 100644 index 0000000..999c574 --- /dev/null +++ b/080_blog/00040_Haskell/00010_Links-and-Literature/index.md @@ -0,0 +1,17 @@ +# Haskell - Books, Links and Papers + +A growing collection of external links and books concerning Haskell. + +* **Learn You a Haskell** for Great Good by Marian Lipovaca +* **Real World Haskell** by Bryan O'Sullivan, Don Stewart, and John Goerzen +* **Parallel and Concurrent Programming in Haskell** by Simon Marlow +* **Haskell Wiki** +* **UPENN CIS 194** +* **What I Wish I Knew When Learning Haskell** by Stephen Diehl +* **Data61 Course** +* **Monads for functional programming (paper)** by Philip Wadler +* **Functional Pearl (paper)** +* **Why Functional Programming Matters (paper)** +* **Mailing Lists** +* **IRC** #haskell at chat.freenode.at +* **Monadic Warsaw** diff --git a/080_blog/00040_Haskell/00010_Links-and-Notes-and-Literature/index.md b/080_blog/00040_Haskell/00010_Links-and-Notes-and-Literature/index.md deleted file mode 100644 index 2eb1215..0000000 --- a/080_blog/00040_Haskell/00010_Links-and-Notes-and-Literature/index.md +++ /dev/null @@ -1,69 +0,0 @@ -# Haskell - -## Books, Links and Papers - -* **Learn You a Haskell** for Great Good by Marian Lipovaca -* **Real World Haskell** by Bryan O'Sullivan, Don Stewart, and John Goerzen -* **Parallel and Concurrent Programming in Haskell** by Simon Marlow - -* **Haskell Wiki** -* **UPENN CIS 194** -* **What I Wish I Knew When Learning Haskell** by Stephen Diehl -* **Data61 Course** - -* **Monads for functional programming (paper)** by Philip Wadler -* **Functional Pearl (paper)** -* **Why Functional Programming Matters (paper)** - -* **Mailing Lists** -* **IRC** #haskell at chat.freenode.at -* **Monadic Warsaw** - - -## xmonad-contrib contribution - -Added a pretty printer for empty visible workspaces\ - - -## Some GHC Flags - - -v verbose mode - -O2 level 2 optimizations - -rtsopts allow +RTS flags - -prof enable basic time and allocation profiling - -auto-all cost centers on all top level functions - (you can also add them via the SCC pragma) - -caf-all generate data for CAFs (constant applicative forms) - -fforce-recomp force recompilation - -threaded Use threaed runtime - -eventlog enables +RTS -l flag - - -Wall - -Werror - - Notes: you will obtain the profiling versions of dependancies via: - stack install --profile [libraryname] - - -fprof-auto replaced -auto-all - -fprof-cafs replaced -caf-all - -## Some +RTS flags - - -K set stack limit - -s statistic reporting - -p profiling - -hc extract heap profile - -hy allocation by type - -hd allocation by constructor - -ix x is sampling frequency in seconds. e.g. 0.01) - -Nx x is number of cores to utilize - -l emit log file (can be used threadscope) - -ddump-simpl generate core - - Note: render the heap profile as graph with: hp2ps -e8in -c file.hp - show eventlog with: threadscope file.eventlog - -## monad transformers in action - - Main Control.Monad.Writer Control.Monad.State> runState (runWriterT (get >>= \a -> tell ["foo"] >> put (a*a) >> tell ["bar"] >> tell [show a])) 5 - diff --git a/080_blog/00040_Haskell/00020_GHC-Notes/index.md b/080_blog/00040_Haskell/00020_GHC-Notes/index.md new file mode 100644 index 0000000..c945319 --- /dev/null +++ b/080_blog/00040_Haskell/00020_GHC-Notes/index.md @@ -0,0 +1,39 @@ +# The Glasgow Haskell Compiler + +## Some GHC Flags + + -v verbose mode + -O2 level 2 optimizations + -rtsopts allow +RTS flags + -prof enable basic time and allocation profiling + -auto-all cost centers on all top level functions + (you can also add them via the SCC pragma) + -caf-all generate data for CAFs (constant applicative forms) + -fforce-recomp force recompilation + -threaded Use threaed runtime + -eventlog enables +RTS -l flag + + -Wall + -Werror + + Notes: you will obtain the profiling versions of dependancies via: + stack install --profile [libraryname] + + -fprof-auto replaced -auto-all + -fprof-cafs replaced -caf-all + +## Some +RTS flags + + -K set stack limit + -s statistic reporting + -p profiling + -hc extract heap profile + -hy allocation by type + -hd allocation by constructor + -ix x is sampling frequency in seconds. e.g. 0.01) + -Nx x is number of cores to utilize + -l emit log file (can be used threadscope) + -ddump-simpl generate core + + Note: render the heap profile as graph with: hp2ps -e8in -c file.hp + show eventlog with: threadscope file.eventlog diff --git a/080_blog/00040_Haskell/00030_Xmonad-contribution/index.md b/080_blog/00040_Haskell/00030_Xmonad-contribution/index.md new file mode 100644 index 0000000..1a5bf0f --- /dev/null +++ b/080_blog/00040_Haskell/00030_Xmonad-contribution/index.md @@ -0,0 +1,20 @@ + April 2018 +# Pretty printer for empty visible workspaces + +My little contribution to **xmonad-contrib**, adding functionality to the +marvelous xmonad tiling window manager, I love and use since a couple of +years. + +## Description + +Simple extensions of the pretty printer to differentiate between empty and non-empty visible workspaces. Analogical to the existing functionality for hidden workspaces. Particularly useful if some displays managed by xmonad are turned off temporarily. + +The new 'ppVisibleNoWindows' function was wrapped in a Maybe data type. Its value dafaults to 'Nothing' and 'ppVisible' is used as fallback. + +## Motivation + +My TV is often turned off. Still I want to know if its workspace contains any windows, without having to switch workspaces. + +## Github Link +| _Xmonad-Contrib: Added pretty printer for empty visible workspaces (wrapped in Maybe)_ +| diff --git a/080_blog/00040_Haskell/00065_Base64-Encoder/base64.cast b/080_blog/00040_Haskell/00065_Base64-Encoder/base64.cast index 54f3ab5..b32cd78 100644 --- a/080_blog/00040_Haskell/00065_Base64-Encoder/base64.cast +++ b/080_blog/00040_Haskell/00065_Base64-Encoder/base64.cast @@ -1,226 +1,146 @@ { - "command": null, - "width": 101, - "title": null, - "height": 6, "env": { - "SHELL": "/bin/bash", - "TERM": "screen-256color" + "TERM": "screen-256color", + "SHELL": "/bin/bash" }, + "version": 1, + "command": null, + "title": null, + "width": 90, + "height": 7, + "duration": 26.498611, "stdout": [ [ - 0.020042, + 0.018948, "miguel@megaloman:~/git/haskell/base64$ " ], [ - 0.972847, - "cat /dev/urandom | pv | ./base64 > /dev/null " + 0.831467, + "cat /tmp/random.bin | pv | ./base64 > /dev/null " ], [ - 0.43902, - "\r\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[1Pecho \"Welcome to Base64 encoding\" | ./base64" + 0.269283, + "\r\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[17Pecho \"Hello Base64!\" | ./base64" ], [ - 0.83889, + 1.242802, "\r\n" ], [ - 0.001251, - "V2VsY29tZSB0byBCYXNlNjQgZW5jb2RpbmcK\r\n" + 0.002817, + "SGVsbG8gQmFzZTY0IQo=\r\n" ], [ - 0.000356, + 0.000531, "miguel@megaloman:~/git/haskell/base64$ " ], [ - 1.151505, - "echo \"Welcome to Base64 encoding\" | ./base64" + 0.827791, + "echo \"Hello Base64!\" | ./base64" ], [ - 0.328933, - "\r\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[C\u001b[Ccat /dev/urandom | pv | ./base64 > /dev/null " + 0.207417, + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bcat /tmp/random.bin | pv | ./base64 > /dev/null " ], [ - 0.833, + 0.963475, "\r\n" ], [ - 1.001665, - " 253MiB 0:00:01 [ 253MiB/s] [ <=> ]\r" - ], - [ - 0.999837, - " 500MiB 0:00:02 [ 247MiB/s] [ <=> ]\r" - ], - [ - 1.000048, - " 753MiB 0:00:03 [ 252MiB/s] [ <=> ]\r" - ], - [ - 1.000117, - "1001MiB 0:00:04 [ 247MiB/s] [ <=> ]\r" - ], - [ - 0.999649, - "1.22GiB 0:00:05 [ 251MiB/s] [ <=> ]\r" - ], - [ - 1.000026, - "1.47GiB 0:00:06 [ 250MiB/s] [ <=> ]\r" - ], - [ - 1.000236, - "1.72GiB 0:00:07 [ 253MiB/s] [ <=> ]\r" - ], - [ - 1.000056, - "1.96GiB 0:00:08 [ 252MiB/s] [ <=> ]\r" - ], - [ - 0.999645, - " 2.2GiB 0:00:09 [ 244MiB/s] [ <=> ]\r" - ], - [ - 1.000274, - "2.45GiB 0:00:10 [ 253MiB/s] [ <=> ]\r" - ], - [ - 0.999751, - "2.69GiB 0:00:11 [ 244MiB/s] [ <=> ]\r" + 1.002914, + " 434MiB 0:00:01 [ 434MiB/s] [ <=> ]\r" ], [ - 1.000191, - "2.93GiB 0:00:12 [ 252MiB/s] [ <=> ]\r" + 0.99997, + " 876MiB 0:00:02 [ 441MiB/s] [ <=> ]\r" ], [ - 0.999772, - "3.18GiB 0:00:13 [ 248MiB/s] [ <=> ]\r" + 1.000022, + "1.28GiB 0:00:03 [ 439MiB/s] [ <=> ]\r" ], [ - 1.000312, - "3.43GiB 0:00:14 [ 257MiB/s] [ <=> ]\r" + 1.000032, + "1.73GiB 0:00:04 [ 455MiB/s] [ <=> ]\r" ], [ - 0.999856, - "3.68GiB 0:00:15 [ 254MiB/s] [ <=> ]\r" - ], - [ - 1.000239, - "3.93GiB 0:00:16 [ 253MiB/s] [ <=> ]\r" - ], - [ - 0.99986, - "4.17GiB 0:00:17 [ 248MiB/s] [ <=> ]\r" - ], - [ - 0.999739, - " 4.4GiB 0:00:18 [ 242MiB/s] [ <=> ]\r" - ], - [ - 1.000023, - "4.65GiB 0:00:19 [ 252MiB/s] [ <=> ]\r" - ], - [ - 1.000103, - "4.89GiB 0:00:20 [ 245MiB/s] [ <=> ]\r" - ], - [ - 1.000106, - "5.14GiB 0:00:21 [ 255MiB/s] [ <=> ]\r" - ], - [ - 1.000102, - "5.38GiB 0:00:22 [ 246MiB/s] [ <=> ]\r" - ], - [ - 1.000042, - "5.63GiB 0:00:23 [ 252MiB/s] [ <=> ]\r" - ], - [ - 0.999787, - "5.87GiB 0:00:24 [ 250MiB/s] [ <=> ]\r" - ], - [ - 1.000079, - "6.11GiB 0:00:25 [ 248MiB/s] [ <=> ]\r" + 0.999929, + "2.18GiB 0:00:05 [ 464MiB/s] [ <=> ]\r" ], [ - 1.000035, - "6.36GiB 0:00:26 [ 247MiB/s] [ <=> ]\r" + 0.999976, + "2.64GiB 0:00:06 [ 464MiB/s] [ <=> ]\r" ], [ - 0.999929, - " 6.6GiB 0:00:27 [ 250MiB/s] [ <=> ]\r" + 1.000019, + "3.09GiB 0:00:07 [ 466MiB/s] [ <=> ]\r" ], [ - 0.999966, - "6.84GiB 0:00:28 [ 244MiB/s] [ <=> ]\r" + 1.00003, + "3.55GiB 0:00:08 [ 467MiB/s] [ <=> ]\r" ], [ - 1.000047, - "7.09GiB 0:00:29 [ 252MiB/s] [ <=> ]\r" + 1.0, + "3.99GiB 0:00:09 [ 452MiB/s] [ <=> ]\r" ], [ - 0.999829, - "7.33GiB 0:00:30 [ 250MiB/s] [ <=> ]\r" + 0.999962, + "4.43GiB 0:00:10 [ 451MiB/s] [ <=> ]\r" ], [ - 0.99996, - "7.57GiB 0:00:31 [ 245MiB/s] [ <=> ]\r" + 1.000027, + "4.88GiB 0:00:11 [ 459MiB/s] [ <=> ]\r" ], [ - 1.000063, - "7.81GiB 0:00:32 [ 248MiB/s] [ <=> ]\r" + 1.000061, + "5.32GiB 0:00:12 [ 451MiB/s] [ <=> ]\r" ], [ - 0.999947, - "8.06GiB 0:00:33 [ 251MiB/s] [ <=> ]\r" + 0.999986, + "5.76GiB 0:00:13 [ 449MiB/s] [ <=> ]\r" ], [ - 1.000249, - " 8.3GiB 0:00:34 [ 246MiB/s] [ <=> ]\r" + 0.999944, + "6.19GiB 0:00:14 [ 441MiB/s] [ <=> ]\r" ], [ - 1.000158, - "8.55GiB 0:00:35 [ 253MiB/s] [ <=> ]\r" + 0.999991, + "6.64GiB 0:00:15 [ 453MiB/s] [ <=> ]\r" ], [ - 0.999634, - "8.79GiB 0:00:36 [ 254MiB/s] [ <=> ]\r" + 1.000027, + "7.07GiB 0:00:16 [ 442MiB/s] [ <=> ]\r" ], [ - 1.000289, - "9.04GiB 0:00:37 [ 251MiB/s] [ <=> ]\r" + 1.00001, + " 7.5GiB 0:00:17 [ 442MiB/s] [ <=> ]\r" ], [ - 0.99977, - "9.29GiB 0:00:38 [ 251MiB/s] [ <=> ]\r" + 1.000009, + "7.93GiB 0:00:18 [ 440MiB/s] [ <=> ]\r" ], [ - 1.000013, - "9.53GiB 0:00:39 [ 248MiB/s] [ <=> ]\r" + 0.999988, + "8.37GiB 0:00:19 [ 449MiB/s] [ <=> ]\r" ], [ - 1.000045, - "9.77GiB 0:00:40 [ 247MiB/s] [ <=> ]\r" + 1.000024, + "8.81GiB 0:00:20 [ 445MiB/s] [ <=> ]\r" ], [ - 0.999859, - " 10GiB 0:00:41 [ 248MiB/s] [ <=> ]\r" + 0.99992, + "9.26GiB 0:00:21 [ 461MiB/s] [ <=> ]\r" ], [ - 0.760304, - "^C\r\n" + 1.000016, + "9.71GiB 0:00:22 [ 461MiB/s] [ <=> ]\r" ], [ - 0.000409, - "\r\n" + 0.129892, + "9.77GiB 0:00:22 [ 451MiB/s] [ <=> ]\r\r\n" ], [ - 0.000128, + 0.000604, "miguel@megaloman:~/git/haskell/base64$ " ] - ], - "version": 1, - "duration": 46.348438 + ] } \ No newline at end of file diff --git a/080_blog/00040_Haskell/00065_Base64-Encoder/index.md b/080_blog/00040_Haskell/00065_Base64-Encoder/index.md index 3fd87ee..cabf19e 100644 --- a/080_blog/00040_Haskell/00065_Base64-Encoder/index.md +++ b/080_blog/00040_Haskell/00065_Base64-Encoder/index.md @@ -1,15 +1,12 @@ Miguel's Base64 Encoder ======================= February 19, 2018 - Initially coded on a cold winter afternoon to fully understand **base64 encoding** and play with -**Haskell**, which is always an indisputable pleasure. - -Coded in _big anger_, due to my friend Nick's fairy tales about saving his encrypted binary -data in plain _ASCII_ configuration files, featuring strange letters and non-printable characters. :smile: +**Haskell**, which is always an indisputable pleasure. Hacked together in _big anger_, due to my +friend Nick's fairy tales about saving his encrypted binary data in plain _ASCII_ +configuration files,... featuring strange letters and non-printable characters. :smile: -_EDIT_: After optimizing my naive implementation, the encoder now reaches speeds -of around **240MB/s** on a single core of my _i7-4790K_. +After optimizing quite a bit, the encoder performs around **460MB/s** on a single core of my _i7-4790K_. diff --git a/080_blog/00040_Haskell/00130_Calculator-on-Parsec-and-GTK/calc.png b/080_blog/00040_Haskell/00130_Calculator-on-Parsec-and-GTK/calc.png new file mode 100644 index 0000000..19b47f0 Binary files /dev/null and b/080_blog/00040_Haskell/00130_Calculator-on-Parsec-and-GTK/calc.png differ diff --git a/080_blog/00040_Haskell/00130_Calculator-on-Parsec-and-GTK/index.md b/080_blog/00040_Haskell/00130_Calculator-on-Parsec-and-GTK/index.md index 381b017..cc0aa28 100644 --- a/080_blog/00040_Haskell/00130_Calculator-on-Parsec-and-GTK/index.md +++ b/080_blog/00040_Haskell/00130_Calculator-on-Parsec-and-GTK/index.md @@ -1,23 +1,21 @@ + May 2018 Simple Calculator on Parsec and GTK =================================== - May 3, 2018 - -![](calc.png){.img-fluid .border} +![](scale_calc.png){ width=220px } Today I implemented this simple stupid calulator as a side effect of playing around with parsec [1] and haskells gtk3 [2] bindings, as well as glade [3] - an interactive user interface designer. -Source Files +Source Files ------------ -* [calc.hs](calc.hs) -* [calc.glade](calc.glade) +* Ref --- - [1] https://hackage.haskell.org/package/parsec - [2] https://hackage.haskell.org/package/gtk3 - [3] https://glade.gnome.org/ +* [1] +* [2] +* [3] diff --git a/080_blog/00040_Haskell/00140_Minimalistic-SVG-Generator/index.md b/080_blog/00040_Haskell/00140_Minimalistic-SVG-Generator/index.md index 8211ba2..2c21d91 100644 --- a/080_blog/00040_Haskell/00140_Minimalistic-SVG-Generator/index.md +++ b/080_blog/00040_Haskell/00140_Minimalistic-SVG-Generator/index.md @@ -1,7 +1,7 @@ + May 2018 A Minimalistic SVG Generator ============================ - May 11, 2018 A minimalistic SVG generator for my humble requirements. @@ -10,22 +10,18 @@ They might grow someday however... The SVG in the following screenshot was generated from the following code to demonstrate a simple use case. -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.haskell .numberLines} -svgExample1 = svgAddList (svgEmpty (svgShGray 200) 300 200) $ - [ svgRedLine (0,0) (200,200) - ,svgRedLine (300,0) (100,200) - ,svgBluePoint (33,133) - ,svgBluePoint (33,22) - ,svgBluePoint (66,25) - ,svgFilledTriangle svgBlack svgWhite (20,20) (100,100) (10,90) - ,svgFilledCircle svgWhite svgGreen (150,120) 30 - ]++ - map (svgBluePoint . (,) 250) [50,60..150] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The source code below was auto-fetched from: + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.haskell .numberLines} +{BEGIN:EMBED} +https://gitweb.softwarefools.com/?p=miguel/haskell.git;a=blob_plain;f=simpleSVG/TestSvg.hs +{END:EMBED} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ![](svg.png){.img-fluid .border} Source Files ------------ -* [SimpleSvg.hs](SimpleSvg.hs) +* diff --git a/080_blog/00040_Haskell/00150_Applicative-vs-Monadic-Parsing/index.md b/080_blog/00040_Haskell/00150_Applicative-vs-Monadic-Parsing/index.md index f9b3a4e..6e4418b 100644 --- a/080_blog/00040_Haskell/00150_Applicative-vs-Monadic-Parsing/index.md +++ b/080_blog/00040_Haskell/00150_Applicative-vs-Monadic-Parsing/index.md @@ -1 +1,175 @@ -Coming sooner... or later. + March 2019 +# Applicative vs. Monadic Parsing + +Some _real world parsers_ as _Parsec_, let us choose between applicative and +monadic parsing. The applicative style should be sufficient to parse +_context-free_ languages and is easier to reason about, but it is not capable +of parsing _context-sensitive_ grammars. + +## Functor, Applicative, Alternative, Monad + +Before we discuss Applicative and Monadic Parsing, it is important to +understand what Functors, Applicative Functors, Alternatives and Monads +have to offer. When in doubt simply look up the type-class definition. + +Two well-known data types which are instances of all of the above are +**Maybe** and **List**. Try it yourself in _GHCi_. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.haskell .numberLines} +-- Maybe as Functor +fmap (+20) (Just 10) +fmap (+20) (Nothing) + +-- List as Functor +fmap (+20) [1..10] + +-- Maybe as Applicative Functor +Nothing <*> Just (22) +Just (+1) <*> Nothing +Just (+15) <*> Just (22) + +-- List as Applicative Functor +[]<*>[1..5] +[(+1),(+15)]<*>[] +[(+1),(+15)]<*>[1..5] + +-- Maybe as Alternative +Nothing <|> Just 5 +Just 5 <|> Nothing +Just 22 <|> Just 10 + +-- List as Alternative +[1..5] <|> [5..10] + +-- Maybe as Monad +Just 5 >>= Just . (+10) +Just 5 >>= return . (+10) +Just 10 >>= return . (+5) >>=return . (+10) +Nothing >>= return . (+5) >>=return . (+10) +Just 10 >>= \x-> return (x*2) >>=return . (+x`div`2) + +-- List as Monad +[1..10] >>= (:[]) . (*5) +[1..5] >>= return . (^2) +[[1..5],[5..10],[],[12]]>>=id +[[1..5],[5..10],[],[12]]>>= map (*4) +[1..5] >>= \a -> [100..100+a] >>= \b -> return (a+b) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +## Simple Parser + +Our simple toy Parser simply encapsulates a parsing function that returns +_Nothing_ if parsing fails. Otherwise a _pair_ consisting of the parsed and +unparsed input inside its respective elements. + +Notice that we made our Parser instance of all the type-classes already. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.haskell .numberLines} +data Parser a b = Parser (a->Maybe (b,a)) + +instance Functor (Parser a) where + fmap f p = Parser g + where g inp = case parse p inp of Just (x,y) -> Just (f x,y) + _ -> Nothing + +instance Applicative (Parser a) where + pure v = Parser (\inp -> Just (v,inp)) + pg <*> px = Parser g + where g inp = case parse pg inp of Just (f,b) -> parse (fmap f px) b + _ -> Nothing + +instance Alternative (Parser a) where + empty = Parser (\_ -> Nothing) + p1 <|> p2 = Parser g + where g inp = case parse p1 inp of Nothing -> parse p2 inp + x -> x + +instance Monad (Parser a) where + return = pure + p >>= f = Parser g + where g inp = case parse p inp of Just (a,b) -> parse (f a) b + _ -> Nothing + +parse :: Parser a b -> a -> Maybe (b,a) +parse (Parser f) inp = f inp +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +## Primitives + +We also need at least a minimal set of primitives to parse something. +Note that the primitives can give you the effects of Applicative or +Alternative even if there's no instance (as dmwit pointed out on #haskell). +E.g. the _word_ primitive below, could not be composed, by combining the +_char_ parsers in an applicative style only. + +The _num_ parser makes use of the _some_ combinator which requires our +Parser to be an instance of _Alternative_ as well. _Applicative_ +alone is of limited use in practice since without it, we also lack +the <|> combinator. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.haskell .numberLines} +word :: String -> Parser String String +word w = Parser g where l = length w + g inp = if take l inp == w then Just (w,drop l inp) + else Nothing + +satisfy :: (Char -> Bool) -> Parser String Char +satisfy f = Parser g where g (x:xs) | f x = Just (x,xs) + g _ = Nothing + +space :: Parser String Char +space = satisfy (==' ') + +char :: Char -> Parser String Char +char c = satisfy (==c) + +notChar :: Char -> Parser String Char +notChar c = satisfy (/=c) + +num :: Parser String Int +num = read <$> some (satisfy isDigit) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +## Applicative / Alternative parsing + +Let's parse something! + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.haskell .numberLines} +-- well-formed parentheses are the canonical example of a context-free grammar +parsePar = concat <$> some parseP where parseP = word "()" <|> (char '(' *> parsePar <* char ')') +parse parsePar "((()())()())" + +-- a simple context-free language with matching pairs of a's and b's, which is not regular +parseAB = (\a x b -> a:x++"b") <$> char 'a' <*> parseAB <*> char 'b' <|> word "ab" +parse parseAB "aaaaabbbbb" + +-- parse basic mathematical operations and calulate the results. +parseOp op sig = (pure (op) <* many space <*> num <* many space <* char sig <* many space <*> num ) +parse (parseOp (+) '+' <|> parseOp (-) '-' <|> parseOp (*) '*' <|> parseOp (div) '/') " 111 * 747 " +parse (parseOp (+) '+' <|> parseOp (-) '-' <|> parseOp (*) '*' <|> parseOp (div) '/') "111+747" +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +## Monadic parsing of context-sensitive grammars + +The canonical non-context-free language can not be caputred by applicative parsing anymore: $$\{a^n b^n c^n : n \geqslant 1\}$$ + +The following monadic parser will work here: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.haskell .numberLines} +parseABC = length <$> (many $ char 'a') >>= \la -> + length <$> (many $ char 'b') >>= \lb -> + length <$> (many $ char 'c') >>= \lc -> + if la==lb&&lb==lc then pure ("ABCok") else empty + +parse parseABC "aaaaabbbbbccccc" +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +## Summary + +As usual, use the simplest tool that will suffice :smile: + +## Ref / Further Reading + +* +* +* diff --git a/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index.md b/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index.md new file mode 100644 index 0000000..5060081 --- /dev/null +++ b/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index.md @@ -0,0 +1,20 @@ +# Pandoc Color Themes + +Color-themes for syntax-highlighting obtained from Pandoc. +E.g. To get the pygments theme you need to have some source-code embedded +in your markdown and run: + + stack exec pandoc -- -s file.md --highlight-style pygments + +Then you can extract the css from the resulting standalone html file. +Here you can find my extracted html files for reference: + +* [breezedark](index_breezedark.html) +* [espresso](index_espresso.html) +* [haddock](index_haddock.html) +* [kate](index_kate.html) +* [monochrome](index_monochrome.html) +* [pygments](index_pygments.html) +* [tango](index_tango.html) +* [zenburn](index_zenburn.html) + diff --git a/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_breezedark.html b/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_breezedark.html new file mode 100644 index 0000000..6b89b97 --- /dev/null +++ b/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_breezedark.html @@ -0,0 +1,117 @@ + + + + + + + index + + + + + + + + diff --git a/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_espresso.html b/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_espresso.html new file mode 100644 index 0000000..6b0d627 --- /dev/null +++ b/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_espresso.html @@ -0,0 +1,113 @@ + + + + + + + index + + + + + + + + diff --git a/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_haddock.html b/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_haddock.html new file mode 100644 index 0000000..5c5af29 --- /dev/null +++ b/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_haddock.html @@ -0,0 +1,109 @@ + + + + + + + index + + + + + + + + diff --git a/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_kate.html b/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_kate.html new file mode 100644 index 0000000..03aa0c6 --- /dev/null +++ b/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_kate.html @@ -0,0 +1,117 @@ + + + + + + + index + + + + + + + + diff --git a/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_monochrome.html b/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_monochrome.html new file mode 100644 index 0000000..60c229d --- /dev/null +++ b/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_monochrome.html @@ -0,0 +1,96 @@ + + + + + + + index + + + + + + + + diff --git a/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_pygments.html b/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_pygments.html new file mode 100644 index 0000000..e637f29 --- /dev/null +++ b/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_pygments.html @@ -0,0 +1,114 @@ + + + + + + + index + + + + + + + + diff --git a/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_tango.html b/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_tango.html new file mode 100644 index 0000000..f76564b --- /dev/null +++ b/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_tango.html @@ -0,0 +1,113 @@ + + + + + + + index + + + + + + + + diff --git a/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_zenburn.html b/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_zenburn.html new file mode 100644 index 0000000..f186f69 --- /dev/null +++ b/080_blog/00040_Haskell/00200_Estatico-Page-Maker/00_pandoc_colors/index_zenburn.html @@ -0,0 +1,113 @@ + + + + + + + index + + + + + + + + diff --git a/080_blog/00040_Haskell/00200_Estatico-Page-Maker/index.md b/080_blog/00040_Haskell/00200_Estatico-Page-Maker/index.md index 279c721..fe78da5 100644 --- a/080_blog/00040_Haskell/00200_Estatico-Page-Maker/index.md +++ b/080_blog/00040_Haskell/00200_Estatico-Page-Maker/index.md @@ -1,13 +1,12 @@ + April 2018 # estático - static website generator - April 12, 2018 - -Two weeks ago I decided to switch my website from a well known PHP +A few weeks ago I decided to switch my website from a well known PHP driven CMS solution, to a light and static set of HTML pages. -And so I wrote a simple static website generator in -**Haskell**. Of course I know that there are already hundreds out there, -but I wanted my own masturbatory solution. +And so I wrote ... a simple static website generator in **Haskell**. +Of course I know that there is already plenty out there, but I wanted my +own masturbatory solution. I use **pandoc** et al. for most of the work anyway. @@ -30,7 +29,13 @@ Build it with _stack_ or use the docker images. * * -## Example Usage +## Pandoc Themes + +Here I put together the themes available for syntax-highlighting, extracted +from **pandoc**: [./pandoc\_colors](./pandoc_colors) + +## Example Usage (Docker) + __NOTE: make sure DIR\_OUT exists and is a free directory__ You can use the example websites inside the examples/ directory for a start. @@ -49,7 +54,7 @@ Or if you want to test it locally use some local DIR\_OUT and HTML\_ROOT instead DIR_OUT=/home/miguel/testpage HTML_ROOT=/home/miguel/testpage -The only real life example I know of, is this very page: _idziorek.net_ -You can find it's sources here: +This very page: _idziorek.net_ is a real-world example and you can find +it's sources here: * diff --git a/080_blog/00040_Haskell/00_00150_Applicative-vs-Monadic-Parsing/index.md b/080_blog/00040_Haskell/00_00150_Applicative-vs-Monadic-Parsing/index.md new file mode 100644 index 0000000..f9b3a4e --- /dev/null +++ b/080_blog/00040_Haskell/00_00150_Applicative-vs-Monadic-Parsing/index.md @@ -0,0 +1 @@ +Coming sooner... or later. diff --git a/080_blog/00040_Hex-Converter/hexman.html b/080_blog/00040_Hex-Converter/hexman.html new file mode 100644 index 0000000..86af3ef --- /dev/null +++ b/080_blog/00040_Hex-Converter/hexman.html @@ -0,0 +1,170 @@ + + + + + + + + +
+ +
+
+
+

Miguel's Converter

+

Convert numbers between different bases. Supports decimal, octal, binary and hex. You can use a custom base as well.

+
+
+
+ +
+
+
+ +
+
+ 10 +
+
+
+ +
+
+
+ +
+
+ 8 +
+
+
+ +
+
+
+ +
+
+ 2 +
+
+ +
+
+
+ + + +
+
+
+ +
+
+ 16 +
+
+
+ +
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+

Hacked together by miguel

+

powered by JavaScript and Bootstrap.

+
+
+
+ + + + + diff --git a/080_blog/00040_Hex-Converter/index.md b/080_blog/00040_Hex-Converter/index.md new file mode 100644 index 0000000..1f837db --- /dev/null +++ b/080_blog/00040_Hex-Converter/index.md @@ -0,0 +1,5 @@ +# Hex Converter + +My little online converter between different bases: +[link](hexman.html) + diff --git a/080_blog/00100_Webkit-Keyboardless-Navigation/index.md b/080_blog/00100_Webkit-Keyboardless-Navigation/index.md index 5299563..224c9bb 100644 --- a/080_blog/00100_Webkit-Keyboardless-Navigation/index.md +++ b/080_blog/00100_Webkit-Keyboardless-Navigation/index.md @@ -1,8 +1,7 @@ + April 2018 Miguel's Surfing Quick Links ============================ - April 12, 2018 - Since I do not want to depend on JavaScript all of the time, I tried to integrate simple keyboard-only navigation directly into the webkit2gtk+, as a web extension. @@ -18,7 +17,7 @@ The DOM is manipulated on the fly by the browser without any JavaScript involved A little video demonstrating what was achieved so far (inside the glorious, webkit2gtk+ based, suckless surf browser): -