32 Commits

Author SHA1 Message Date
e24ef4e2d8 New draft post and add menu 2025-06-02 22:38:43 -04:00
555e1f57d5 add tags 2025-05-29 18:25:13 -04:00
954536602f Update theme and new make targets 2025-05-29 11:18:52 -04:00
1645042922 Add fedi link
Link needs to contain rel="me" for verification
2025-05-28 20:08:58 -04:00
6c0ad94800 regen and update Makefile 2025-05-28 20:05:38 -04:00
88ab4756e4 Update home page and asciinema poster
Also remove trailing whitespace in all files
2025-05-28 17:31:56 -04:00
67bdd8b49a make casts local 2025-05-28 17:21:41 -04:00
149518e65e change to theme 2025-05-28 17:15:43 -04:00
794723d726 make build clean 2025-05-20 23:17:10 -04:00
e8bce84bf8 update existing 2025-05-20 23:13:03 -04:00
f3c98b3e46 add shortcode for collapsable section 2024-07-05 02:05:55 -04:00
d2a3d53e54 Update asciinema and hugo version 2024-06-27 10:02:29 -04:00
425dd6cdd2 update base url 2024-04-19 17:45:30 -04:00
6205d19bbb Add new post unix-sockets-perms 2024-04-19 17:40:49 -04:00
83e8868495 Add new post unix-sockets-perms 2024-04-19 17:38:40 -04:00
ffd7b06cc0 update build 2024-04-18 20:54:29 -04:00
88aa2e8d11 update deps 2024-04-18 20:46:41 -04:00
6f3700406d add submodule setup to README 2023-08-07 20:39:16 -04:00
01c450d93f hugo version upgrade 2023-08-07 20:18:34 -04:00
77b856fa63 change submodule url 2023-08-04 15:49:28 -04:00
f722b41f5d change pipe to vertical bar 2023-08-04 15:33:14 -04:00
4aef9c3d46 Update bootstrap
Add targets for build
2023-07-26 18:32:34 -04:00
cebeaf6fdd track blog generated output in git submodule 2023-07-26 15:40:15 -04:00
26f89fcb29 update date and add rss 2023-07-26 15:32:20 -04:00
c91d595938 final first post 2023-07-26 15:18:06 -04:00
c14a238f5f add cast, tags 2023-07-24 23:54:51 -04:00
cf4ac9c430 Merge pull request 'Add asciinema' (#1) from asciinema into main
Reviewed-on: #1
2023-07-22 20:18:01 -04:00
e288d17eb8 Add asciinema shortcode and try in Playground 2023-07-22 20:15:39 -04:00
06c5f6b8ff Add make target to download asciinema 2023-07-22 19:47:32 -04:00
43bf72297c update Makefile to new path 2023-07-22 19:42:57 -04:00
f3c41ab0e1 move up hugo to root 2023-07-22 19:34:17 -04:00
8a882f9157 remove old site 2023-07-22 19:30:32 -04:00
42 changed files with 3133 additions and 338 deletions

4
.gitignore vendored
View File

@ -1,2 +1,2 @@
/dist
/build
.hugo_build.lock
tags

6
.gitmodules vendored Normal file
View File

@ -0,0 +1,6 @@
[submodule "public"]
path = public
url = https://gitea.balki.me/balki/blog-op
[submodule "themes/mytheme"]
path = themes/mytheme
url = https://gitea.balki.me/balki/no-js-hugo-theme.git

View File

@ -1,14 +1,20 @@
.PHONY: update-bootstrap
update-bootstrap:
curl -L "https://cdn.jsdelivr.net/npm/bootstrap@5/dist/css/bootstrap.min.css" -o assets/bootstrap.min.css
curl -L "https://cdn.jsdelivr.net/npm/bootstrap@5/dist/js/bootstrap.min.js" -o assets/bootstrap.min.js
.PHONY: build
build:
./build.sh
.PHONY: pulltheme
pulltheme:
git -C themes/mytheme pull
.PHONY: deploy
deploy:
rsync -av dist desk:/var/www/balki.me
git -C public push
ssh desk git -C /var/www/balki.me/public pull
.PHONY: build
build:
rm -rf public/*
hugo --logLevel debug
.PHONY: serve
serve:
hugo server -D --bind "0.0.0.0" --navigateToChanged -p 2323
tags:
~/projects/mine/hugotags/hugotags.sh ~/projects/notmine/hugoDocs/content/en > tags

View File

@ -1 +1,18 @@
# Again blog
# Source of balki.me
## Asciinema
Followed instructions from here: https://jenciso.github.io/blog/embedding-asciinema-cast-in-your-hugo-site/
Asciinema uses wasm which needs CSP unsafe-eval. Ref: https://www.aaron-powell.com/posts/2019-11-27-using-webassembly-with-csp-headers/
## Submodule for generated output
Tracking hugo generated output in git enables to see differences easily before pushing. Also helpful to compare differences after hugo version upgrade.
Below commands help to add a public url for the web UI and also private ssh url for pushing
```bash
git submodule add https://gitea.balki.me/balki/blog-op public
cd public
git config remote.origin.url gitea:balki/blog-op
```

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,18 +0,0 @@
#!/usr/bin/bash
# copy assets
cp -r assets/ dist/
make_page() {
name="$1"
title="$2"
cp templates/index.tmpl.html "build/$name.html"
sed -i "s/<title>/&$title/" "build/$name.html"
pandoc "pages/$name.md" > "build/$name-content.html"
sed -i "/<main>/r build/$name-content.html" "build/$name.html"
cp "build/$name.html" dist/
}
make_page index Home
make_page stuff Stuff

11
content/_index.md Normal file
View File

@ -0,0 +1,11 @@
---
title: "Home"
date: 2023-05-31T09:14:56-04:00
---
Just another dev blog.
* git: https://gitea.balki.me/balki
* github: https://github.com/balki
* Fediverse: {{< myfedilink >}} `@balki@balki.me`
* RSS: https://blog.balki.me/index.xml

View File

@ -0,0 +1,35 @@
---
title: "Playground"
date: 2023-07-22T19:56:37-04:00
draft: true
asciinema: true
---
# Playground for hugo
{{< asciinema key="demo" >}}
There should be a asciinema cast above!
{{< details title="Click to see sample json" >}}
```json
{
"external_tracker_url": "https://github.com/caddyserver/caddy/issues",
"external_tracker_format": "https://github.com/caddyserver/caddy/issues/{index}",
"external_tracker_style": "numeric",
"external_tracker_regexp_pattern": ""
}
```
{{< /details >}}
SWBrqK9fAC6XuZ7eUl3xwnW8SOfekv01TntKdNl/0+noC4Xel+A2elveBYSxh4gWBtMqXR0mT7+8
N1jVF/o/Q19m8JF8UC9SiJP01CGDJoROcN2ijdyguLg76A0B2tltU+eqlbm46Pml+Ukndda1wxdY
eWs1favc/qsN2txx5jL/6srrEEVIKr3p6ov4hOVtju0dswaseknxZagMfaBwbk6KNGS9r5Nmk+MY
0jdYOfcBIHGB/IxvifV+ux5l/C7VK/PBFOm6t/qtVbczDiPtzngOcsR/CQOej5Qfi+2mXEVbci53
GMois/cjJF4vSU7/OcdxCkkLpN42UKyFOPiR3TczXrsM0kt1Zl/y8huf9KLkRC61MD2Zn/FOvl4U
Jsd9CsVNqN2DO5ABxHqSJ5oI9d03rJilWFunJ6jURH8CyfQv5vJ8ORQmMZdBF1DaeXm6K7/R26lY
ArRpYtgWNhzDWhyGSM2E3/XGvE1w4iZ/u8ml8K6R+tInxYRd1+6ScdTr0NgweuXbnk/27G66+NVv
LX3t9d+rWvwdJBzibimLzy6Rnxq6XO1CSmBVTagr4edyJe76GqSS2RMhk3zbdUyP5gyPrYyCDQn5
/0rQsHmzGd9izC6Gjuk7hu10Y3eWi5DCfrDGfyrADO90uYqXrW2tjliwdRJuZtSuRxbOVaY3G3UX
MPG6pRH/byyKTduN2RS4VNo73ZkQOOooQ3NQErGPc29yeWdvLoA7DB5rsMf7V0XZcpLrUVM6SoQf
<!-- vim: set lw=DETAILS_FDM: -->

View File

@ -0,0 +1,209 @@
---
title: "Mirroring git repositories with Gitea"
date: 2024-06-27T10:05:46-04:00
draft: true
tags:
- gitea
- curl
- yq
categories:
- development
---
[Gitea][1] is an awesome self hosted git forge. I use the [pull-mirror][2]
feature to mirror many git repos (mostly from github). In this post, I want to
share few maintenance scripts I ran that connects to [gitea-api][14] using
[yq][] and [curl][].
<!--more-->
# TODO
* Change mirror interval
* Disable for mirror repos by default actions
* use jo https://github.com/jpmens/jo
* get just latest mirror and apply the settings
## Setup
### API token
Go to `https://gitea.balki.me/user/settings/applications` and Generate new
Token with write permission for repositories.
# TODO
set base url
## Why Mirror?
1. Remote sites may disappear one day.
2. Better local code search. Github does not allow code search without signing
in.
3. Tools like vim-plugins can use the local urls which is better for privacy.
4. Setup notification when a repository creates a new tag.
## Dumb crawlers problem
My gitea [instance][3] is public and had all mirror repos public as well. This
caused a huge network traffic from bots.
I created an [organization][4] without public visibility and made it own all
the mirror repos.
```
yq --version
yq (https://github.com/mikefarah/yq/) version v4.44.1
curl -V | head -c 11
curl 8.8.0
```
## API token
## Hooks for notification
[Hooks][5]
Lets first download the list of all mirror repos
```bash
TOKEN=d88446542e844f4da4ba75bbb85bd694a71907b5
curl "https://gitea.balki.me/api/v1/repos/search?limit=100&mode=mirror" \
-H "accept: application/json" \
-H "Authorization: token $TOKEN" \
-o mirror-repos.json
```
References
1. API doc: https://gitea.balki.me/api/swagger#/repository/repoSearch
Create a [hook][5] manually in one repo and get the hook using the API
```bash
curl -s "https://gitea.balki.me/api/v1/repos/MirrorWatch/snac2/hooks?page=1&limit=10" \
-H "Authorization: token $TOKEN" | yq -P -oj
```
Sample Output:
```json
[
{
"id": 32,
"type": "telegram",
"branch_filter": "tag",
"config": {
"content_type": "json",
"url": "https://api.telegram.org/bot1169894068:J1JVbV3f2vEQpdnPqFANfhjWZrFuUCJs1EW/sendMessage?chat_id=-1008910751069"
},
"events": [
"create"
],
"authorization_header": "",
"active": true,
"updated_at": "2024-06-20T20:54:33-04:00",
"created_at": "2024-06-20T20:54:33-04:00"
}
]
```
Now loop through all mirror repos and add the same webook. Remove unwanted fields like `id`, `created_at`, etc.,
```bash
yq -r '.data[] | .full_name' mirror-repos.json | while read -r repo; do
echo "$repo"
curl "https://gitea.balki.me/api/v1/repos/$repo/hooks" \
-H "Authorization: token $TOKEN" \
--json @- <<-EOM
{
"active": true,
"branch_filter": "tag",
"config": {
"content_type": "json",
"url": "https://api.telegram.org/bot1169894068:J1JVbV3f2vEQpdnPqFANfhjWZrFuUCJs1EW/sendMessage?chat_id=-1008910751069"
},
"events": [
"create"
],
"type": "telegram"
}
EOM
echo "============"
done
```
## Fixing issues and pr links
Fix the issue url setting in first repo as shown [here][7].
Get the json representataion.
```bash
yq '.data[] | .external_tracker ' mirror-repos.json | head
```
Sample output
```json
{
"external_tracker_url": "https://github.com/caddyserver/caddy/issues",
"external_tracker_format": "https://github.com/caddyserver/caddy/issues/{index}",
"external_tracker_style": "numeric",
"external_tracker_regexp_pattern": ""
}
```
Now loop throug all repos and update. Making sure only add to github repos and
they are not already updated
```bash
yq -r '.data[]
| select(.original_url == "*github*" and has("internal_tracker") )
| "\(.full_name) \(.original_url)"' mirror-repos.json | while read -r repo og; do
echo "Repo is $repo and github origin url is $og"
curl "https://gitea.balki.me/api/v1/repos/$repo" \
-H "Authorization: token $TOKEN" \
-X PATCH \
--json @- <<-EOM
{
"external_tracker": {
"external_tracker_url": "${og%.git}/issues",
"external_tracker_format": "${og%.git}/issues/{index}",
"external_tracker_style": "numeric",
"external_tracker_regexp_pattern": ""
}
}
EOM
done
yq -r '.data[] | .full_name' mirror-repos.json | while read -r repo; do
echo "$repo"
jo has_actions=false | curl "https://gitea.balki.me/api/v1/repos/$repo" \
-H "Authorization: token $TOKEN" \
-X PATCH \
--json @-
done
```
### Doc links
* yq: [select][8], [has][9], [string interpolation][10]
* bash: [parameter expansion][11], [here-doc][12]
* curl: [`--json`][13]
[1]: https://github.com/go-gitea/gitea
[2]: https://docs.gitea.com/usage/repo-mirror#pulling-from-a-remote-repository
[3]: https://gitea.balki.me
[4]: https://docs.gitea.com/usage/permissions#organization-repository
[5]: https://docs.gitea.com/usage/webhooks
[6]: https://docs.gitea.com/development/api-usage
[7]: https://github.com/go-gitea/gitea/issues/18986
[8]: https://mikefarah.gitbook.io/yq/operators/select
[9]: https://mikefarah.gitbook.io/yq/operators/has#select-checking-for-existence-of-deep-paths
[10]: https://mikefarah.gitbook.io/yq/operators/string-operators#interpolation
[11]: https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
[12]: https://www.gnu.org/software/bash/manual/html_node/Redirections.html#Here-Documents
[13]: https://everything.curl.dev/http/post/json.html
[14]: https://gitea.balki.me/api/swagger#/repository/repoSearch

View File

@ -0,0 +1,7 @@
---
title: "Revive Blog"
date: 2025-05-29T18:26:59-04:00
draft: true
---
{{% gitea repo=balki/hugotags path=hugotags.sh lang=bash %}}

View File

@ -0,0 +1,74 @@
---
title: "Securing communication between webserver and app"
date: 2024-04-19T17:31:06-04:00
tags:
- unix-sockets
- tmpfiles.d
- webserver
categories:
- sysadmin
---
Webapps usually listen on a random tcp port and a web server forwards the
requests to it. Webserver handles tls, static asset serving and sometimes
authentication, bruteforce check etc., However any local user in the system can
directly connect to the app's listen port bypassing the web server and thus
loose the protections offered by the webserver.
### Unix sockets
Unix sockets are special files in filesystem that processes can use to
communicate instead of tcp ports. Since they are files, filesytem ownership and
permissions can be used to restrict which system-users can listen or connect to
them
### Caddy ↔ Gitea
I use [Caddy][1] web server which reverse-proxies to [Gitea][2] server. For
caddy to connect to gitea and also disallow anyother user to connect, we want a
socket like below
```bash
srw-rw---- 1 gitea caddy 0 Apr 17 21:24 /run/gitea.sock
```
Unfortunately neither `user caddy` nor `user gitea`, can create such socket.
Regular users can only create files owned by themselves. Only root can
create/change ownership of files and folders.
### `tmpfiles.d` to rescue
[tmpfiles.d][3] provides a way to do it. Since it is run as root, it can create
files and directories as any user.
```bash
cat /etc/tmpfiles.d/caddy-run-unix.conf
d /run/gitea-caddy 0750 gitea caddy -
```
Above config creates below directory every time on startup.
```bash
sudo ls -ld /run/gitea-caddy/
drwxr-x--- 2 gitea caddy 60 Apr 17 21:24 /run/gitea-caddy/
```
With those permissions and ownership, only `user gitea` can create the socket
in `/run/gitea-caddy` and only `user caddy` can `cd` into that directory.
```bash
sudo ls -l /run/gitea-caddy/web.sock
srw-rw-rw- 1 gitea gitea 0 Apr 17 21:24 /run/gitea-caddy/web.sock
```
The socket file permission can be more liberal as no other user can read into
the `/run/gitea-caddy` directory
### Bonus!
If your app does not connect to any external services, it can even be run in a
[private network][4].
[1]: https://caddyserver.com
[2]: https://gitea.com
[3]: https://man.archlinux.org/man/tmpfiles.d.5
[4]: https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#PrivateNetwork=

View File

@ -0,0 +1,184 @@
{"version": 2, "width": 105, "height": 27, "timestamp": 1690255394, "env": {"SHELL": "/bin/zsh", "TERM": "tmux-256color"}}
[0.603476, "o", "\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r"]
[0.605686, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[44mbalki@archlinux\u001b[49m \u001b[1m\u001b[32m~/projects/mine/vimfun/stt\r\n\r\u001b[37m % \u001b[0m\u001b[37m\u001b[39m\u001b[49m\u001b[K\u001b[?2004h"]
[1.043556, "o", "b"]
[1.123276, "o", "\bba"]
[1.203174, "o", "t"]
[1.301279, "o", " "]
[1.613306, "o", "c"]
[1.691404, "o", "o"]
[1.76925, "o", "m"]
[1.917246, "o", "m"]
[2.287072, "o", "o"]
[2.369433, "o", "n"]
[2.529079, "o", "."]
[2.807484, "o", "v"]
[2.887561, "o", "i"]
[2.987485, "o", "m"]
[3.570353, "o", "\u001b[?2004l\r\r\n"]
[3.58573, "o", "\r\u001b[38;5;238m───────┬─────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[m\r\n \u001b[38;5;238m│ \u001b[0mFile: \u001b[1mcommon.vim\u001b[0m\u001b[m\r\n\u001b[38;5;238m───────┼─────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[m\r\n\u001b[38;5;238m 1\u001b[0m \u001b[38;5;238m│\u001b[0m \u001b[m\r\n\u001b[38;5;238m 2\u001b[0m \u001b[38;5;238m│\u001b[0m \u001b[38;5;81mlet\u001b[0m\u001b[38;5;231m \u001b[0m\u001b[38;5;231mg:mapleader\u001b[0m\u001b[38;5;231m = \u001b[0m\u001b[38;5;186m' '\u001b[0m\u001b[m\r\n\u001b[38;5;238m 3\u001b[0m \u001b[38;5;238m│\u001b[0m \u001b[38;5;81mset\u001b[0m\u001b[38;5;231m splitbelow splitright\u001b[0m\u001b[m\r\n\u001b[38;5;238m───────┴─────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[m\r\n\r\u001b[K"]
[3.587155, "o", "\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r"]
[3.589198, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[44mbalki@archlinux\u001b[49m \u001b[1m\u001b[32m~/projects/mine/vimfun/stt\r\n\r\u001b[37m % \u001b[0m\u001b[37m\u001b[39m\u001b[49m\u001b[K\u001b[?2004h"]
[4.995693, "o", "v"]
[5.055642, "o", "\bvi"]
[5.174006, "o", "m"]
[5.273744, "o", " "]
[5.41173, "o", "-"]
[5.571713, "o", "-"]
[5.753233, "o", "c"]
[5.931673, "o", "l"]
[6.089803, "o", "e"]
[6.16969, "o", "a"]
[6.331837, "o", "n"]
[6.47983, "o", " "]
[6.557859, "o", "-"]
[6.813152, "o", "S"]
[6.984113, "o", " "]
[7.224383, "o", "c"]
[7.326254, "o", "o"]
[7.446336, "o", "m"]
[7.588254, "o", "m"]
[7.810388, "o", "o"]
[7.930429, "o", "n"]
[8.108401, "o", "."]
[8.462427, "o", "v"]
[8.541417, "o", "i"]
[8.608111, "o", "m"]
[9.234495, "o", " "]
[9.534188, "o", "-"]
[9.784079, "o", "S"]
[10.408508, "o", " "]
[10.528223, "o", "s"]
[10.686292, "o", "t"]
[10.830104, "o", "t"]
[11.008242, "o", "."]
[11.245051, "o", "v"]
[11.390101, "o", "i"]
[11.488703, "o", "m"]
[12.704646, "o", "\u001b[?2004l\r\r\n"]
[12.71955, "o", "\u001b[?1000h\u001b[?1049h\u001b[?1h\u001b=\u001b[?2004h"]
[12.720463, "o", "\u001b[1;27r\u001b[27m\u001b[24m\u001b[23m\u001b[0m\u001b[H\u001b[J\u001b[2;1H▽\u001b[6n\u001b[2;1H \u001b[3;1H\u001bPzz\u001b\\\u001b[0%m\u001b[6n\u001b[3;1H \u001b[1;1H\u001b[>c"]
[12.720681, "o", "\u001b[?25l\u001b[2;1H\u001b[94m~ \u001b[3;1H~ \u001b[4;1H~ \u001b[5;1H~ \u001b[6;1H~ \u001b[7;1H~ \u001b[8;1H~ \u001b[9;1H~ \u001b[10;1H~ \u001b[11;1H~ \u001b[12;1H~ \u001b[13;1H~ \u001b[14;1H~ \u001b[15;1H~ \u001b[16;1H~ \u001b[17;1H~ \u001b[18;1H~ \u001b[19;1H~ "]
[12.720799, "o", "\u001b[20;1H~ \u001b[21;1H~ \u001b[22;1H~ \u001b[23;1H~ \u001b[24;1H~ \u001b[25;1H~ \u001b[26;1H~ \u001b[0m\u001b[27;88H0,0-1\u001b[9CAll\u001b[8;45HVIM - Vi IMproved\u001b[10;45Hversion 9.0.1676\u001b[11;41Hby Bram Moolenaar et al.\u001b[12;32HVim is open source and freely distributable\u001b[14;39HHelp poor children in Uganda!\u001b[15;30Htype :help iccf\u001b[34m<Enter>\u001b[0m for information \u001b[17;30Htype :q\u001b[34m<Enter>\u001b[0m to exit \u001b[18;30Htype :help\u001b[34m<Enter>\u001b[0m or \u001b[34m<F1>\u001b[0m for on-line help\u001b[19;30Htype :help version9\u001b[34m<Enter>\u001b[0m for version info\u001b[1;1H\u001b[34h\u001b[?25h"]
[14.428684, "o", "\u001b[?25l\u001b[27;78H:\u001b[1;1H\u001b[27;78H\u001b[K\u001b[27;1H:\u001b[?1000l\u001b[34h\u001b[?25h"]
[14.830782, "o", "e"]
[15.026614, "o", "d"]
[15.106625, "o", "i"]
[15.204778, "o", "t"]
[15.268723, "o", " "]
[15.848928, "o", "c"]
[15.968866, "o", "h"]
[16.026805, "o", "e"]
[16.106825, "o", "a"]
[16.346622, "o", "t"]
[16.586891, "o", "."]
[16.724942, "o", "s"]
[16.824854, "o", "h"]
[17.483213, "o", "\r"]
[17.484646, "o", "\u001b[?1000h\u001b[?25l\"cheat.sh\" \u001b[27;12H\u001b[K\u001b[27;12H6L, 57B"]
[17.493031, "o", "\u001b[1;1H\u001b[38;5;130mecho\u001b[0m\u001b[31m hi\u001b[0m\r\ndate\u001b[2;5H\u001b[K\u001b[3;1HVIMST \u001b[38;5;130msleep\u001b[0m \u001b[31m4000\u001b[0m\u001b[3;17H\u001b[K\u001b[4;1Hdate\u001b[4;5H\u001b[K\u001b[5;1H\u001b[38;5;130mecho\u001b[0m\u001b[31m bye\u001b[0m\u001b[5;9H\u001b[K\u001b[6;1HVIMST ctrl l\u001b[6;13H\u001b[K\u001b[8;45H\u001b[94m \u001b[10;45H \u001b[11;41H \u001b[12;32H \u001b[14;39H \u001b[15;30H \u001b[17;30H \u001b[18;30H \u001b[19;30H \u001b[0m\u001b[27;88H1,1\u001b[11CAll\u001b[1;1H\u001b[34h\u001b[?25h"]
[18.57496, "o", "\u001b[?25l\u001b[27;78H:\u001b[1;1H\u001b[27;1H\u001b[K\u001b[27;1H:\u001b[?1000l\u001b[34h\u001b[?25h"]
[18.747096, "o", "v"]
[18.865071, "o", "e"]
[18.965219, "o", "r"]
[19.145075, "o", "t"]
[19.341239, "o", " "]
[19.567871, "o", "t"]
[19.627258, "o", "e"]
[19.745251, "o", "r"]
[19.960829, "o", "m"]
[20.101664, "o", "i"]
[20.221785, "o", "n"]
[20.319265, "o", "a"]
[20.459327, "o", "l"]
[20.793599, "o", "\r"]
[20.793953, "o", "\u001b[?1000h\u001b[?25l"]
[20.797471, "o", "\u001b[1;54H\b\u001b[7m|\u001b[2;53H|\u001b[3;53H|\u001b[4;53H|\u001b[5;53H|\u001b[6;53H|\u001b[7;53H|\u001b[8;53H|\u001b[9;53H|\u001b[10;53H|\u001b[11;53H|\u001b[12;53H|\u001b[13;53H|\u001b[14;53H|\u001b[15;53H|\u001b[16;53H|\u001b[17;53H|\u001b[18;53H|\u001b[19;53H|\u001b[20;53H|\u001b[21;53H|\u001b[22;53H|\u001b[23;53H|\u001b[24;53H|\u001b[25;53H|\r\ncheat.sh 1,1 All \u001b[0m\u001b[1;54H \u001b[2;54H \u001b[3;54H \u001b[4;54H \u001b[5;54H \u001b[6;54H \u001b[7;54H \u001b[8;54H \u001b[9;54H \u001b[10;54H \u001b[11;54H \u001b[12;54H \u001b[13;54H \u001b[14;54H \u001b[15;54H \u001b[16;54H \u001b[17;54H \u001b[18;54H \u001b[19;54H \u001b[20;54H \u001b[21;54H \u001b[22;54H \u001b[23;54H \u001b[24;54H \u001b[25;54H \u001b[26;54H\u001b[1m\u001b[97m\u001b[42m!/bin/zsh [running] 0,0-1 All\u001b[1;54H\u001b[34h\u001b[?25h"]
[21.340332, "o", "\u001b[?25l\u001b[0m\u001b[27;95H^W\u001b[1;54H\u001b[34h\u001b[?25h"]
[21.396446, "o", "\u001b[?25l\u001b[1C\u001b[34h\u001b[?25h\u001b[50C\u001b[1;54H\u001b[1C\b\u001b[?25l\u001b[34h\u001b[?25h"]
[21.398352, "o", "\u001b[?25l\u001b[15C\u001b[34h\u001b[?25h\u001b[1C\u001b[26C\u001b[1;54H\u001b[2;54H\u001b[3C"]
[21.398702, "o", "\u001b[?25l\u001b[1;54H\u001b[44mbalki@archlinux\u001b[0m\u001b[1C\u001b[1m\u001b[32m~/projects/mine/vimfun/stt\u001b[0m\u001b[2;54H\u001b[1m\u001b[37m % \u001b[34h\u001b[?25h"]
[21.739615, "o", "\u001b[?25l\u001b[0m\u001b[27;95H \u001b[2;57H\u001b[27;95H^Wh\u001b[2;57H"]
[21.739691, "o", "\u001b[27;95H \u001b[1;1H\u001b[26;1H\u001b[1m\u001b[7mcheat.sh 1,1 All \u001b[0m\u001b[97m\u001b[42m!/bin/zsh [running] 1,1 Top\u001b[1;1H\u001b[34h\u001b[?25h"]
[22.89177, "o", "\u001b[?25l\u001b[0m\u001b[27;95H<20>\u001b[1;1H\u001b[34h\u001b[?25h"]
[22.931714, "o", "\u001b[?25l\u001b[27;95H \u001b[1;1H\u001b[?1000l\u001b[?1000h\u001b[34h\u001b[?25h"]
[22.933412, "o", "\u001b[?25l\u001b[2;57Hecho hi\u001b[1;1H\u001b[34h\u001b[?25h"]
[22.936354, "o", "\u001b[?25l\u001b[3;54Hhi\u001b[1;1H\u001b[34h\u001b[?25h"]
[22.94211, "o", "\u001b[?25l\u001b[4;54H\u001b[44mbalki@archlinux\u001b[0m\u001b[1C\u001b[1m\u001b[32m~/projects/mine/vimfun/stt\u001b[0m\u001b[5;54H\u001b[1m\u001b[37m % \u001b[1;1H\u001b[34h\u001b[?25h"]
[24.507692, "o", "\u001b[?25l\u001b[0m\u001b[27;95HV\u001b[1;1H"]
[24.508117, "o", "\u001b[27;95H1\u001b[1;1H\u001b[1C\u001b[38;5;130m\u001b[47mcho\u001b[0m\u001b[31m\u001b[47m hi\u001b[0m\u001b[47m \u001b[0m\u001b[27;1H\u001b[1m-- VISUAL LINE --\u001b[0m\u001b[27;95H\u001b[K\u001b[27;95H1\u001b[1;1H\u001b[34h\u001b[?25h"]
[24.789755, "o", "\u001b[?25l\u001b[27;95Hj\u001b[1;1H"]
[24.790102, "o", "\u001b[27;95H2\u001b[2;1H\u001b[1;1H\u001b[38;5;130m\u001b[47me\u001b[0m\r\nd\u001b[47mate \u001b[0m\u001b[26;35H\u001b[1m\u001b[7m2\u001b[2;1H\u001b[34h\u001b[?25h"]
[25.077917, "o", "\u001b[?25l\u001b[0m\u001b[27;95Hj\u001b[2;1H"]
[25.078442, "o", "\u001b[27;95H3\u001b[3;1H\u001b[2;1H\u001b[47md\r\n\u001b[0mV\u001b[47mIMST \u001b[0m\u001b[38;5;130m\u001b[47msleep\u001b[0m\u001b[47m \u001b[0m\u001b[31m\u001b[47m4000\u001b[0m\u001b[47m \u001b[0m\u001b[26;35H\u001b[1m\u001b[7m3\u001b[3;1H\u001b[34h\u001b[?25h"]
[25.353911, "o", "\u001b[?25l\u001b[0m\u001b[27;95Hj\u001b[3;1H"]
[25.354276, "o", "\u001b[27;95H4\u001b[4;1H\u001b[3;1H\u001b[47mV\r\n\u001b[0md\u001b[47mate \u001b[0m\u001b[26;35H\u001b[1m\u001b[7m4\u001b[4;1H\u001b[34h\u001b[?25h"]
[25.781257, "o", "\u001b[?25l\u001b[0m\u001b[27;95Hj\u001b[4;1H"]
[25.781502, "o", "\u001b[27;95H5\u001b[5;1H\u001b[4;1H\u001b[47md\u001b[0m\u001b[5;2H\u001b[38;5;130m\u001b[47mcho\u001b[0m\u001b[31m\u001b[47m bye\u001b[0m\u001b[47m \u001b[0m\u001b[26;35H\u001b[1m\u001b[7m5\u001b[5;1H\u001b[34h\u001b[?25h"]
[26.178059, "o", "\u001b[?25l\u001b[0m\u001b[27;95H<20>\u001b[5;1H\u001b[34h\u001b[?25h"]
[26.238921, "o", "\u001b[?25l\u001b[27;95H5 \u001b[5;1H\u001b[27;95H \u001b[1;1H\u001b[?1000l\u001b[?1000h\u001b[38;5;130mecho\u001b[0m\u001b[31m hi\u001b[0m \r\ndate \r\nVIMST \u001b[38;5;130msleep\u001b[0m \u001b[31m4000\u001b[0m \r\ndate \u001b[5;2H\u001b[38;5;130mcho\u001b[0m\u001b[31m bye\u001b[0m \u001b[27;1H\u001b[K\u001b[26;35H\u001b[1m\u001b[7m1\u001b[1;1H\u001b[34h\u001b[?25h"]
[26.239565, "o", "\u001b[?25l\u001b[0m\u001b[5;57Hecho hi\u001b[1;1H\u001b[34h\u001b[?25h"]
[26.240481, "o", "\u001b[?25l\u001b[6;54Hhi\u001b[1;1H\u001b[34h\u001b[?25h"]
[26.246317, "o", "\u001b[?25l\u001b[7;54H\u001b[44mbalki@archlinux\u001b[0m\u001b[1C\u001b[1m\u001b[32m~/projects/mine/vimfun/stt\u001b[0m\u001b[8;54H\u001b[1m\u001b[37m % \u001b[0mdate\u001b[1;1H\u001b[34h\u001b[?25h\u001b[?25l\u001b[34h\u001b[?25h"]
[26.250645, "o", "\u001b[?25l\u001b[9;54HMon 24 Jul 2023 11:23:41 PM EDT\u001b[1;1H\u001b[34h\u001b[?25h"]
[26.251354, "o", "\u001b[?25l\u001b[34h\u001b[?25h"]
[26.256797, "o", "\u001b[?25l\u001b[10;54H\u001b[44mbalki@archlinux\u001b[0m\u001b[1C\u001b[1m\u001b[32m~/projects/mine/vimfun/stt\u001b[0m\u001b[11;54H\u001b[1m\u001b[37m % \u001b[1;1H\u001b[34h\u001b[?25h"]
[30.242604, "o", "\u001b[?25l\u001b[34h\u001b[?25h"]
[30.2437, "o", "\u001b[?25l\u001b[0m\u001b[11;57Hdate\u001b[1;1H\u001b[34h\u001b[?25h\u001b[?25l\u001b[34h\u001b[?25h"]
[30.24826, "o", "\u001b[?25l\u001b[12;54HMon 24 Jul 2023 11:23:45 PM EDT\u001b[1;1H\u001b[34h\u001b[?25h"]
[30.248916, "o", "\u001b[?25l\u001b[34h\u001b[?25h"]
[30.254193, "o", "\u001b[?25l\u001b[13;54H\u001b[44mbalki@archlinux\u001b[0m\u001b[1C\u001b[1m\u001b[32m~/projects/mine/vimfun/stt\u001b[0m\u001b[14;54H\u001b[1m\u001b[37m % \u001b[0mecho\u001b[1;1H\u001b[34h\u001b[?25h"]
[30.254912, "o", "\u001b[?25l\u001b[14;62Hbye\u001b[1;1H\u001b[34h\u001b[?25h"]
[30.255543, "o", "\u001b[?25l\u001b[15;54Hbye\u001b[1;1H\u001b[34h\u001b[?25h"]
[30.260783, "o", "\u001b[?25l\u001b[16;54H\u001b[44mbalki@archlinux\u001b[0m\u001b[1C\u001b[1m\u001b[32m~/projects/mine/vimfun/stt\u001b[0m\u001b[17;54H\u001b[1m\u001b[37m % \u001b[1;1H\u001b[34h\u001b[?25h"]
[32.366676, "o", "\u001b[?25l\u001b[0m\u001b[27;95HG\u001b[1;1H\u001b[27;95H \u001b[6;1H\u001b[26;35H\u001b[1m\u001b[7m6\u001b[6;1H\u001b[34h\u001b[?25h"]
[33.622721, "o", "\u001b[?25l\u001b[0m\u001b[27;95Hk\u001b[6;1H\u001b[27;95H \u001b[5;1H\u001b[26;35H\u001b[1m\u001b[7m5\u001b[5;1H\u001b[34h\u001b[?25h"]
[33.804893, "o", "\u001b[?25l\u001b[0m\u001b[27;95Hk\u001b[5;1H\u001b[27;95H \u001b[4;1H\u001b[26;35H\u001b[1m\u001b[7m4\u001b[4;1H\u001b[34h\u001b[?25h"]
[38.012689, "o", "\u001b[?25l\u001b[26;35H6,8\u001b[6;8H\u001b[34h\u001b[?25h"]
[38.359024, "o", "\u001b[?1000l\u001b[?1000h\u001b[?25l\u001b[34h\u001b[?25h"]
[38.360913, "o", "\u001b[?25l\u001b[0m\u001b[2;57H \u001b[3;54H \u001b[4;54H \u001b[5;54H \u001b[6;54H \u001b[7;54H \u001b[8;54H \u001b[9;54H \u001b[10;54H \u001b[11;54H \u001b[12;54H \u001b[13;54H \u001b[14;54H \u001b[15;54H \u001b[16;54H \u001b[17;54H \u001b[6;8H\u001b[34h\u001b[?25h"]
[39.454289, "o", "\u001b[?25l\u001b[26;35H\u001b[1m\u001b[7m5\u001b[5;8H\u001b[34h\u001b[?25h"]
[39.618716, "o", "\u001b[?1000l\u001b[?1000h\u001b[?25l\u001b[34h\u001b[?25h"]
[39.620149, "o", "\u001b[?25l\u001b[0m\u001b[2;57Hecho bye\u001b[5;8H\u001b[34h\u001b[?25h"]
[39.621315, "o", "\u001b[?25l\u001b[3;54Hbye\u001b[5;8H\u001b[34h\u001b[?25h"]
[39.623263, "o", "\u001b[?25l\u001b[4;54H\u001b[44mbalki@archlinux\u001b[0m\u001b[1C\u001b[1m\u001b[32m~/projects/mine/vimfun/stt\u001b[0m\u001b[5;54H\u001b[1m\u001b[37m % \u001b[5;8H\u001b[34h\u001b[?25h"]
[40.77026, "o", "\u001b[?25l\u001b[0m\u001b[26;35H\u001b[1m\u001b[7m1,7\u001b[1;7H\u001b[34h\u001b[?25h"]
[40.93504, "o", "\u001b[?1000l\u001b[?1000h\u001b[?25l\u001b[34h\u001b[?25h"]
[40.936345, "o", "\u001b[?25l\u001b[0m\u001b[5;57Hecho hi\u001b[1;7H\u001b[34h\u001b[?25h"]
[40.937653, "o", "\u001b[?25l\u001b[6;54Hhi\u001b[1;7H\u001b[34h\u001b[?25h"]
[40.943521, "o", "\u001b[?25l\u001b[7;54H\u001b[44mbalki@archlinux\u001b[0m\u001b[1C\u001b[1m\u001b[32m~/projects/mine/vimfun/stt\u001b[0m\u001b[8;54H\u001b[1m\u001b[37m % \u001b[1;7H\u001b[34h\u001b[?25h"]
[42.629357, "o", "\u001b[?25l\u001b[0m\u001b[26;35H\u001b[1m\u001b[7m6,12\u001b[6;12H\u001b[34h\u001b[?25h"]
[44.032006, "o", "\u001b[?25l\u001b[0m\u001b[27;95H:\u001b[6;12H\u001b[27;95H\u001b[K\u001b[27;1H:\u001b[?1000l\u001b[34h\u001b[?25h"]
[44.193796, "o", "q"]
[44.393755, "o", "a"]
[44.71981, "o", "!"]
[45.462189, "o", "\r\u001b[?1000h\u001b[?25l\u001b[?1000l\u001b[?2004l"]
[45.462284, "o", "\u001b[27;1H\u001b[K\u001b[27;1H\u001b[?2004l\u001b[?1l\u001b>\u001b[?1049l\u001b[34h\u001b[?25h"]
[45.464866, "o", "\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r"]
[45.470145, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[44mbalki@archlinux\u001b[49m \u001b[1m\u001b[32m~/projects/mine/vimfun/stt\r\n\r\u001b[37m % \u001b[0m\u001b[37m\u001b[39m\u001b[49m\u001b[K\u001b[?2004h"]
[47.152206, "o", ":"]
[47.614152, "o", "\b: "]
[47.812179, "o", "T"]
[47.892206, "o", "h"]
[48.044315, "o", "a"]
[48.102131, "o", "n"]
[48.202197, "o", "k"]
[48.320023, "o", "s"]
[48.460466, "o", " "]
[48.540361, "o", "f"]
[48.618256, "o", "o"]
[48.718252, "o", "r"]
[48.778222, "o", " "]
[49.134702, "o", "w"]
[49.234434, "o", "a"]
[49.310933, "o", "t"]
[49.596789, "o", "c"]
[49.734453, "o", "h"]
[49.834509, "o", "i"]
[49.952548, "o", "n"]
[50.03251, "o", "g"]
[50.352787, "o", "!"]
[50.909101, "o", "\u001b[?2004l\r\r\n"]
[50.914851, "o", "\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r"]
[50.916752, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[44mbalki@archlinux\u001b[49m \u001b[1m\u001b[32m~/projects/mine/vimfun/stt\r\n\r\u001b[37m % \u001b[0m\u001b[37m\u001b[39m\u001b[49m\u001b[K\u001b[?2004h"]
[51.490522, "o", "\u001b[?2004l\r\r\n"]

View File

@ -0,0 +1,116 @@
---
title: Vim Send To Terminal
date: 2023-07-26T15:23:22-04:00
asciinema: true
tags:
- vim
categories:
- development
---
### Semi automatic scripts with vim `:terminal`
<!--more-->
Sometimes, fully automating a task is not worth the effort. So I end up running
a set of commands usually from a cheat sheet text file slightly modifying the
arguments each time. I used the below in vim to send line under cursor to vim's
`:terminal` open in a split
```vim
:call term_list()[0]->term_sendkeys(getline('.') .. "\<CR>")
```
To send another line `@:` and then for every other line `@@`. This works because, last
command run is stored in `register :` and the last macro executed using `@` is
stored in `register @`.
To do the same another day, `:call te<UP arrow>` to recall from vim's command
history. Or better, add a function and mapping.
```vim
def SendToTerminal()
if term_list()->empty()
echomsg "No Terminal windows found"
return
endif
terms[0]->term_sendkeys(getline(.) .. "\<CR>")
enddef
nnoremap <silent><leader>s call SendToTerminal()<CR>
```
### More cool features
For most use-cases that was enough. However added a few more nice features
which is very helpful when you need it
1. Support sending a range of lines (visual selection) at a time. E.g. Send a
function block to a python shell
2. Add a delay between lines in milliseconds. This is useful when the previous
command reads from standard input and takes some time to complete
3. Support sending `ctrl` characters like `ctrl d`, `ctrl c` etc,
```vim
def g:SendRangeToTerminal(start_line: number, end_line: number)
const terms = term_list()
if terms->empty()
echomsg "No Terminal windows found"
return
endif
var line_num = start_line
for line in getline(start_line, end_line)
line_num += 1
const spl_cmd = line->matchlist('\vVIMST (sleep|ctrl) ([0-9]+|[a-z])')
if !spl_cmd->empty()
const [_, cmd, arg1; _] = spl_cmd
if cmd == "sleep"
timer_start(str2nr(arg1), (_) => g:SendRangeToTerminal(line_num, end_line))
return
elseif cmd == "ctrl"
terms[0]->term_sendkeys(nr2char(char2nr(arg1) - 96))
continue
endif
endif
terms[0]->term_sendkeys(line .. "\<CR>")
endfor
enddef
command -range -bar SendToTerm :call g:SendRangeToTerminal(<line1>, <line2>)
vnoremap <silent><leader>s :SendToTerm<CR>
nnoremap <silent><leader>s :SendToTerm<CR>
```
### More cool mapping
Wouldn't it be nice to just double-click commands with mouse? Like a simple GUI! ;)
```vim
nnoremap <silent><2-LeftMouse> :SendToTerm<CR>
```
Or just hit `Enter`?
```vim
nnoremap <buffer> <CR> :SendToTerm \| norm j<CR>
```
Automatically add those mappings for `cheat.sh`
```vim
autocmd BufNewFile,BufRead cheat.sh nnoremap <buffer> <CR> :SendToTerm \| norm j<CR>
autocmd BufNewFile,BufRead cheat.sh nnoremap <buffer> <silent><2-LeftMouse> :SendToTerm<CR>
```
### Demo
{{< asciinema key="vimstt" poster="npt:0:23" startAt="0:18" >}}
### Using
Copying above snippets to your vimrc should work in a recent vim. Checked in
ubuntu 22.04 and archlinux. Git: [repo](https://gitea.balki.me/balki/vimfun/src/branch/main/stt/stt8.vim)
### neovim/tmux/screen
Since neovim uses a different terminal API, above snippets don't work in
neovim. [vim-slime](https://github.com/jpalardy/vim-slime) plugin (available
since 2007!) supports different types of terminal. However it does not support
adding delay and `ctrl` characters in text.

32
hugo.yaml Normal file
View File

@ -0,0 +1,32 @@
baseURL: https://blog.balki.me/
languageCode: en-us
title: Balki's Blog
theme: mytheme
markup:
highlight:
# This setting makes code highlighting use theme's colors instead of hugo's default
noClasses: false
params:
themeStyleSwitcher: true
footerText: "[theme](https://gitea.balki.me/balki/no-js-hugo-theme)"
showTagList: false
menu:
main:
- identifier: home
name: Home
pageRef: /
weight: 1
- identifier: gitea
name: Gitea
url: https://gitea.balki.me/balki
weight: 2
- identifier: github
name: Github
url: https://github.com/balki
weight: 3
- identifier: rss
name: RSS
url: https://blog.balki.me/index.xml
weight: 4

2
hugo/.gitignore vendored
View File

@ -1,2 +0,0 @@
.hugo_build.lock
/public/

View File

@ -1,3 +0,0 @@
baseURL: http://blog.balki.me/
languageCode: en-us
title: Balki's Blog

View File

@ -1,9 +0,0 @@
---
title: "Home"
date: 2023-05-31T09:14:56-04:00
draft: false
---
Balki's Blog
============

View File

@ -1,103 +0,0 @@
---
title: Vim Send To Terminal
date: 2023-07-15T20:18:03-04:00
---
### Semi automatic scripts with vim `:terminal`
<!--more-->
For a long time, I used the below to send current line to vim's `:terminal`
```vim
:call term_list()[0]->term_sendkeys(getline('.') .. "\<CR>")
```
This is very useful if you have a text file with complex shell commands. To run
again, `@:` and then again, `@@`. This works because, last command run is
stored in `register :` and the last macro executed using `@` is stored in
`register @`. And then to run another day, do `:call te<UP arrow>` to recall
from vim's command history.
Since this was very useful, I then wrapped it in a function and added a mapping
```vim
def SendToTerminal()
if term_list()->empty()
echomsg "No Terminal windows found"
return
endif
terms[0]->term_sendkeys(getline(.) .. "\<CR>")
enddef
nnoremap <silent><leader>s call SendToTerminal()<CR>
```
### Adding more features
So far good for shell commands. But when working with python, had to send a
block of functions to the `ipython` shell. So added support for range of lines.
But then when sending a range of lines to shell, sometimes there had to be a
small delay (sleep) between commands so that the previous command can complete
and not eat the rest of commands. Then finally added support for sending `ctrl`
characters like `ctrl c`, `ctrl l`
```vim
vim9script
def SendRangeToTerminal(start_line: number, end_line: number, _ = 0)
const terms = term_list()
if terms->empty()
echomsg "No Terminal windows found"
return
endif
var line_num = start_line
for line in getline(start_line, end_line)
line_num += 1
const spl_cmd = line->matchlist('\vVIMST (sleep|ctrl) ([0-9]+|[a-z])?')
if !spl_cmd->empty()
const [_, cmd, arg1; _] = spl_cmd
if cmd == "sleep"
timer_start(arg1->str2nr(), funcref('SendRangeToTerminal', [line_num, end_line]))
return
elseif cmd == "ctrl"
terms[0]->term_sendkeys(nr2char(arg1->char2nr() - 96))
continue
endif
endif
terms[0]->term_sendkeys(line .. "\<CR>")
endfor
enddef
command -range -bar SendToTerm :call <SID>SendRangeToTerminal(<line1>, <line2>)
vnoremap <silent><leader>s :SendToTerm<CR>
nnoremap <silent><leader>s :SendToTerm<CR>
```
Wouldn't it be nice to just double-click commands with mouse? Like a simple GUI! ;)
```vim
nnoremap <silent><2-LeftMouse> :SendToTerm<CR>
```
Or just `Enter`?
```vim
nnoremap <buffer> <CR> :SendToTerm \| norm j<CR>
```
Of course, mapping `Enter` for any file is a bad idea. So lets just map in our cheat file
```vim
autocmd BufNewFile,BufRead cheat.sh {
nnoremap <buffer> <silent><2-LeftMouse> :SendToTerm<CR>
nnoremap <buffer> <CR> :SendToTerm \| norm j<CR>
}
```
### Demo!
### What about neovim/tmux/screen?
I am not the only one who thought about this. See
[vim-slime](https://github.com/jpalardy/vim-slime) since 2007. However it does
not support adding a sleep or sending arbitrary `ctrl` characters without
additional mappings

View File

@ -1,48 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-inline' data: ;">
<title>
{{- block "title" . -}}
{{ .Site.Title }}
{{- end -}}
</title>
<!-- Diable favicon requests: https://stackoverflow.com/a/13416784 -->
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<link href="/assets/bootstrap.min.css" rel="stylesheet" >
<style>
{{- block "styles" . -}}
{{- end -}}
</style>
<script src="/assets/bootstrap.min.js" defer></script>
</head>
<body>
<div class="container" >
<aside>
<nav>
<ul class="nav">
<li class="nav-item"><a class="nav-link" href="/"> Home </a></li>
<li class="nav-item"><a class="nav-link" href="/posts"> Blog </a></li>
<li class="nav-item"><a class="nav-link" href="https://gitea.balki.me/balki"> Gitea </a></li>
<li class="nav-item"><a class="nav-link" href="https://github.com/balki"> Github </a></li>
<!-- TODO
<li class="nav-item"><a class="nav-link" href="/about"> About </a></li>
-->
</ul>
</nav>
</aside>
<main>
{{ block "main" . }}
{{ end }}
</main>
</div>
</body>
</html>

View File

@ -1,6 +0,0 @@
{{ define "main" }}
<h1 class="text-center">Posts</h1>
{{ range .Pages }}
{{ partial "postcard" . }}
{{ end }}
{{ end }}

View File

@ -1,11 +0,0 @@
{{ define "title" }}
{{ .Title }} &ndash; {{ .Site.Title }}
{{ end }}
{{ define "main" }}
<article>
<h1 class="display-3 text-center">{{ .Title }}</h1>
<p class="text-center"><time datetime="{{ .Date }}">{{ .Date.Format "2006-01-02" }}</time></p>
{{ .Content }}
</article>
{{ end }}

View File

@ -1,16 +0,0 @@
{{ define "main" }}
<article>
<div class="text-center m-4">
{{ .Content }}
</div>
<p class="text-center">Under construction. Come back later! :)</p>
<div>
<h4>Recent posts</h4>
{{ range .Pages }}
{{ range .Pages }}
{{ partial "postcard" . }}
{{ end }}
{{ end }}
</div>
</article>
{{ end }}

View File

@ -1,12 +0,0 @@
{{ define "styles" }}
a.title-link {
text-decoration: none;
}
{{ end }}
<div class="card mb-4">
<div class="card-body">
<a class="title-link link-primary" href="{{ .RelPermalink }}" ><h3 class="card-title">{{ .Title }}</h3></a>
<p> {{ .Date.Format "2006-01-02" }} </p>
<p class="card-text"> {{ .Summary }} </p>
</div>
</div>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,12 @@
{{- $url := "" -}}
{{- with .Get "url" -}}
{{- $url = . -}}
{{- else -}}
{{- $url = urls.JoinPath "http://gitea.balki.me" (.Get "repo") "raw/branch/main" (.Get "path") -}}
{{- end -}}
```{{ .Get "lang" }}
{{ with resources.GetRemote $url }}
{{- .Content -}}
{{ end }}
```
[source]({{ $url }})

View File

@ -0,0 +1 @@
<a href="https://social.balki.me/@balki" rel="me" >https://social.balki.me/@balki</a>

View File

@ -1,3 +0,0 @@
Welcome to my site!
I am Balakrishnan Balasubramanian (a) balki. Nothing much here. Checkout the nav bar above for interesting stuff.

View File

@ -1,33 +0,0 @@
# Some cool stuff I built
## vimtabdiff
Simple python script to see diff off two directories with diff of each file in a vim tab. Typically used to replace `git difftool`
<div class="table">
+---------+-------------------------------------------+
| Project | vimtabdiff |
+---------+-------------------------------------------+
| Tags | #python, #vim, #git |
+---------+-------------------------------------------+
| Github | <https://github.com/balki/vimtabdiff> |
+---------+-------------------------------------------+
| Gitea | <https://gitea.balki.me/balki/vimtabdiff> |
+---------+-------------------------------------------+
</div>
## grocery_guy
Telegram bot to manage lists.
<div class="table">
+----------+----------------------------------------------------+
| Project | grocery_guy |
+----------+----------------------------------------------------+
| Tags | #golang, #telegram |
+----------+----------------------------------------------------+
| Gitea | <https://gitea.balki.me/balki/telegram-chklistbot> |
+----------+----------------------------------------------------+
| Telegram | <https://t.me/grocery_guy_bot> |
+----------+----------------------------------------------------+
</div>

1
public Submodule

Submodule public added at e03e9e4c2c

View File

File diff suppressed because it is too large Load Diff

1
static/assets/asciinema-player.min.js vendored Normal file

File diff suppressed because one or more lines are too long

6
static/assets/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

7
static/assets/bootstrap.min.js vendored Normal file

File diff suppressed because one or more lines are too long

42
static/casts/demo.cast Normal file
View File

@ -0,0 +1,42 @@
{"version": 2, "width": 211, "height": 54, "timestamp": 1690070416, "env": {"SHELL": "/bin/zsh", "TERM": "tmux-256color"}}
[0.616662, "o", "\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r"]
[0.651075, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\r\n\u001b[1;36mblog\u001b[0m on \u001b[1;35m \u001b[0m\u001b[1;35masciinema\u001b[0m \u001b[1;31m[\u001b[0m\u001b[1;31m$\u001b[0m\u001b[1;31m!\u001b[0m\u001b[1;31m?\u001b[0m\u001b[1;31m]\u001b[0m \r\n\u001b[1;2;31m⬢\u001b[0m\u001b[1;2;31m [\u001b[0m\u001b[1;2;31mOCI\u001b[0m\u001b[1;2;31m]\u001b[0m \u001b[1;32m\u001b[0m \u001b[K\u001b[?2004h"]
[2.137003, "o", "e"]
[2.144549, "o", "\be\u001b[90mcho bye\u001b[39m\b\b\b\b\b\b\b"]
[2.192516, "o", "\be\u001b[39mc"]
[2.232416, "o", "\u001b[39mh"]
[2.372576, "o", "\u001b[39mo"]
[2.390732, "o", "\u001b[39m "]
[2.774916, "o", "\u001b[39m\"\u001b[39m \u001b[39m \b\b"]
[2.781599, "o", "\u001b[90m{{ .Render }}\" > layouts/index.html\u001b[39m\u001b[35D"]
[3.091004, "o", "\u001b[39mH\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[34D"]
[3.098663, "o", "\u001b[90meh\" | nc 127.0.0.1 8080\u001b[39m\u001b[23D"]
[3.228845, "o", "\u001b[39me"]
[3.42287, "o", "\u001b[39me\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[21D"]
[3.830673, "o", "\b \b"]
[3.849255, "o", "\u001b[90mh\" | nc 127.0.0.1 8080\u001b[39m\u001b[22D"]
[4.059485, "o", "\u001b[39ml\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[21D"]
[4.067668, "o", "\u001b[90ml\" | nc 127.0.0.1 8080\u001b[39m\u001b[22D"]
[4.211281, "o", "\u001b[39ml"]
[4.469571, "o", "\u001b[39mo\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[20D"]
[4.477592, "o", "\u001b[90m\" | nc 127.0.0.1 8080\u001b[39m\u001b[21D"]
[4.943674, "o", "\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[20D"]
[4.951654, "o", "\u001b[90mworld ha ah aha\" | nc 127.0.0.1 8080\u001b[39m\u001b[36D"]
[5.144929, "o", "\u001b[39mw"]
[5.205373, "o", "\u001b[39mo"]
[5.303329, "o", "\u001b[39mr"]
[5.422771, "o", "\u001b[39ml"]
[5.502979, "o", "\u001b[39md"]
[6.684966, "o", "\u001b[39m\"\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[30D"]
[7.170616, "o", "\u001b[?2004l\r\r\n"]
[7.174019, "o", "Hello world\r\n\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r"]
[7.204173, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\r\n\u001b[1;36mblog\u001b[0m on \u001b[1;35m \u001b[0m\u001b[1;35masciinema\u001b[0m \u001b[1;31m[\u001b[0m\u001b[1;31m$\u001b[0m\u001b[1;31m!\u001b[0m\u001b[1;31m?\u001b[0m\u001b[1;31m]\u001b[0m \r\n\u001b[1;2;31m⬢\u001b[0m\u001b[1;2;31m [\u001b[0m\u001b[1;2;31mOCI\u001b[0m\u001b[1;2;31m]\u001b[0m \u001b[1;32m\u001b[0m \u001b[K\u001b[?2004h"]
[10.303159, "o", "e"]
[10.310087, "o", "\be\u001b[90mcho \"Hello world\"\u001b[39m\u001b[17D"]
[10.49929, "o", "\be\u001b[39mx\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[16D"]
[10.505837, "o", "\u001b[90mport EDITOR=vim\u001b[39m\u001b[15D"]
[10.597115, "o", "\u001b[39mi\u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[39m \u001b[14D"]
[10.61047, "o", "\u001b[90mt()\u001b[39m\r\r\n\u001b[90mecho hi\u001b[39m\u001b[K\u001bM\u001b[6C"]
[10.714876, "o", "\u001b[39mt"]
[11.946849, "o", "\u001b[39m \u001b[39m \u001b[1B\r\u001b[K\u001bM\u001b[14C"]
[11.947131, "o", "\u001b[?2004l\u001b[1B\r"]

View File

@ -1,35 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-inline' data: ;">
<meta http-equiv="refresh" content="5000" >
<title></title>
<!-- Diable favicon requests: https://stackoverflow.com/a/13416784 -->
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<link href="assets/bootstrap.min.css" rel="stylesheet" >
<script src="assets/bootstrap.min.js" defer></script>
</head>
<body>
<nav>
<ul class="nav">
<li class="nav-item"><a class="nav-link" href="/"> Home </a></li>
<li class="nav-item"><a class="nav-link" href="https://blog.balki.me"> Blog </a></li>
<li class="nav-item"><a class="nav-link" href="/stuff.html"> Stuff </a></li>
<li class="nav-item"><a class="nav-link" href="https://gitea.balki.me/balki/blog"> Source </a></li>
</ul>
</nav>
<div class="container" >
<main>
</main>
</div>
</body>
</html>

1
themes/mytheme Submodule

Submodule themes/mytheme added at da512608d9