Compare commits

...

24 Commits

Author SHA1 Message Date
6d00283fe2 cmd: show test in journal vacuum 2026-05-01 14:21:48 +02:00
a2c3521c48 add stopping email scams 2026-05-01 13:13:48 +02:00
0a824f10c8 cmd: rephrase text for shell formatting 2026-04-30 20:12:59 +02:00
8bb26740b0 edit users and groups directly 2026-04-30 15:33:23 +02:00
0d053e9a7d cmd: return terminal after ssh freeze 2026-04-30 13:06:14 +02:00
ec3c355ac4 remove necessity to recompile command-lists 2026-04-30 13:03:31 +02:00
2a010a777e make vim links absolute 2026-04-30 00:53:34 +02:00
12064196d2 fix variable syntax 2026-04-30 00:50:02 +02:00
68734cfd1b include markdown as a variable 2026-04-29 17:42:11 +02:00
019736de05 place template makefile 2026-04-29 17:39:37 +02:00
76be2fbd3c fix links 2026-04-29 14:35:17 +02:00
34ef924a09 typo 2026-04-29 12:49:32 +02:00
793d32164e rename pdf to text 2026-04-28 23:56:37 +02:00
39a7317cc5 note: retitle gpg with vim 2026-04-28 19:58:46 +02:00
c06884d434 note: csv to markdown in vim 2026-04-28 18:11:54 +02:00
c25f55054b note: format markdown in vim 2026-04-28 18:01:52 +02:00
73f8dc0feb reformat tables 2026-04-28 17:40:08 +02:00
a4ffedcb6b note: place arch gpu required tags 2026-04-28 13:23:25 +02:00
b27ccb33ab note: how to send email 2026-04-28 02:10:39 +02:00
95b753549b note useage in lowdown.mk example 2026-04-27 17:20:35 +02:00
c586062552 git commit -p 2026-04-27 17:12:52 +02:00
0d25236b27 reword column examples 2026-04-27 17:12:29 +02:00
d53ca311c1 split shell tips into bash and shell 2026-04-27 17:08:41 +02:00
3a7a92de14 edit editors 2026-04-27 15:21:14 +02:00
25 changed files with 532 additions and 128 deletions

View File

@@ -5,6 +5,8 @@ PAGER ?= less -Ri
READER != command -v mdless bat glow less more pg | head -1 READER != command -v mdless bat glow less more pg | head -1
FZF != command -v fzf sk | head -1 FZF != command -v fzf sk | head -1
markdown = $(wildcard */*.md */*/*.md)
ifeq "$(FZF)" "" ifeq "$(FZF)" ""
$(info Install fzf) $(info Install fzf)
endif endif
@@ -32,7 +34,7 @@ default += .dbs/map.fmt
include cmd.mk include cmd.mk
.dbs/head.rec: | .dbs/ $(lists) .dbs/head.rec: | .dbs/
printf '%s\n' '%rec: guide' > $@ printf '%s\n' '%rec: guide' > $@
printf '%s\n' '%key: path' >> $@ printf '%s\n' '%key: path' >> $@
printf '%s\n' '%type: requires rec guide' >> $@ printf '%s\n' '%type: requires rec guide' >> $@
@@ -40,7 +42,7 @@ include cmd.mk
printf '%s\n' '%type: wordcount int' >> $@ printf '%s\n' '%type: wordcount int' >> $@
printf '%s\n\n' '%sort: wordcount' >> $@ printf '%s\n\n' '%sort: wordcount' >> $@
.dbs/new.rec: $(wildcard */*.md */*/*.md) | .dbs/head.rec .dbs/new.rec: $(markdown) | .dbs/head.rec
$(info Updating: $?) $(info Updating: $?)
grep -q guide $@ 2>/dev/null || cp $| $@ grep -q guide $@ 2>/dev/null || cp $| $@
@-$(foreach entry, $?, \ @-$(foreach entry, $?, \

76
chat/send_email.md Normal file
View File

@@ -0,0 +1,76 @@
---
title: Send an email with a CLI command
tags:
- email
requires:
- data/pass.md
---
# Setup the Config
Install `msmtp` and set up the defaults.
```sh
mkdir ~/.config/msmtp/
cat > ~/.config/msmtp/config << EOF
defaults
tls on
auth on
EOF
```
You'll need to fill in some variables, like your provider's hostname and SMTP port.
The `${pass_name}` is just the `pass` command which gives your email password.
```sh
name=posteo
host=posteo.de
port=587
user=bob@posteo.net
pass_name=posteo.net
```
With those in, add that default account.
```sh
cat >> ~/.config/msmtp/config << EOF
account ${name}
host ${host}
port ${port}
user ${user}
from ${user}
passwordeval pass ${pass_name}
```
Finally, set this as the default account:
```sh
account default : ${account} >> ~/.config/msmtp/config
```
# Write an Email
Fill out the headers in a file called `mail`.
```
From: MSMTP ${user}
Subject: Pipes
To: ${recipient_name} <${recipient_email}>
A pipe gives a wise man time to think and a fool something to stick in his
mouth.
```
# Send
Send the email:
```sh
msmtp -t bindrpg@posteo.uk < mail
```

5
cmd.mk
View File

@@ -2,8 +2,6 @@
cmds != recsel command.rec -t command -G bin -CP bin | sort -u cmds != recsel command.rec -t command -G bin -CP bin | sort -u
lists = $(patsubst %,lists/%.md, $(cmds)) lists = $(patsubst %,lists/%.md, $(cmds))
default += $(lists)
get_title = printf 'title: %s\n' '${1}' get_title = printf 'title: %s\n' '${1}'
get_tags = recsel -t $(basename $<) $< -G bin \ get_tags = recsel -t $(basename $<) $< -G bin \
-e 'bin = "$(1)"' -U -CP tag,bin | \ -e 'bin = "$(1)"' -U -CP tag,bin | \
@@ -20,9 +18,6 @@ $(lists): lists/%.md: command.rec | lists/
@printf '%s\n' '---' >> $@ @printf '%s\n' '---' >> $@
@$(call list_commands,$(basename $(notdir $@))) >> $@ @$(call list_commands,$(basename $(notdir $@))) >> $@
.PHONY: cmd
cmd: $(lists) ## Big lists of commands
.PHONY: function .PHONY: function
function: ## Output a search function for .bashrc function: ## Output a search function for .bashrc
${MAKE} --silent --touch query ${MAKE} --silent --touch query

View File

@@ -10,27 +10,27 @@ shell: sh
bin: column bin: column
tag: format tag: format
aim: Reformat file with an explicit separator (`-s`) aim: Reformat user accounts with an explicit separator (`-s`)
cmd: column -ts: /etc/passwd cmd: column -ts: /etc/passwd
shell: sh shell: sh
bin: column bin: column
tag: format tag: format
aim: Sort lines into columns with names aim: Sort user accounts into columns with names
cmd: column -ts: -N User,PW,UID,GID,Description,Home,shell -H PW,GID /etc/passwd cmd: column -ts: -N User,PW,UID,GID,Description,Home,shell -H PW,GID /etc/passwd
note: Hide some columns with `-H`. note: Hide some columns with `-H`.
shell: sh shell: sh
bin: column bin: column
tag: format tag: format
aim: Sort lines into columns and reorder them aim: Sort user accounts into columns and reorder them
cmd: column -ts: -N User,PW,UID,GID,Description,Home,shell -H PW,GID -O User,Description,shell /etc/passwd cmd: column -ts: -N User,PW,UID,GID,Description,Home,shell -H PW,GID -O User,Description,shell /etc/passwd
note: Unspecified items remain. note: Unspecified items remain.
shell: sh shell: sh
bin: column bin: column
tag: format tag: format
aim: Output to json format with `-J` aim: Output user accounts in json format with `-J`
cmd: column -J -ts: -H PW,GID,shell -N User,PW,UID,GID,Description,Home,shell /etc/passwd cmd: column -J -ts: -H PW,GID,shell -N User,PW,UID,GID,Description,Home,shell /etc/passwd
shell: sh shell: sh
bin: column bin: column
@@ -157,12 +157,37 @@ shell: sh
bin: journalctl bin: journalctl
tag: system tag: system
aim: Edit users in /etc/passwd directly
cmd: sudo vipw
note: You can't edit passwords with black magic.
shell: sh
bin: vipw
bin: sudo
tag: system
tag: users
aim: Edit groups in /etc/group directly
cmd: sudo vigr
note: You can't edit passwords with black magic.
shell: sh
bin: vipw
bin: sudo
tag: system
tag: groups
aim: Follow the `ssh` daemon service aim: Follow the `ssh` daemon service
cmd: journalctl -f -u sshd cmd: journalctl -f -u sshd
shell: sh shell: sh
bin: journalctl bin: journalctl
tag: system tag: system
aim: Get back terminal after ssh freezes remote machine
cmd: <Return>~.
shell: sh
bin: ssh
tag: system
tag: comfy
aim: Find errors since a date aim: Find errors since a date
cmd: date=2027-01-01 cmd: date=2027-01-01
+ journalctl --since=${date} --grep="EXT4-fs error" + journalctl --since=${date} --grep="EXT4-fs error"
@@ -170,18 +195,22 @@ shell: sh
bin: journalctl bin: journalctl
tag: system tag: system
aim: Limit the journal's size to 2 gigabytes aim: Limit the systemd's journal size to 2 gigabytes
cmd: journalctl --vacuum-size=2G cmd: journalctl --vacuum-size=2G
+ journalctl --disk-usage
shell: sh shell: sh
bin: journalctl bin: journalctl
tag: system tag: system
tag: logs
aim: Log the fact that you've installed your own `dnsmasq` on your system to `journalctl`, so that you can determine why your system's broken later aim: Log the fact that you've installed your own `dnsmasq` on your system to `journalctl`, so that you can determine why your system's broken later
cmd: logger "Installed new dnsmasq" cmd: logger "Installed new dnsmasq"
+ sudo journalctl -f + sudo journalctl -f
shell: sh shell: sh
bin: journalctl bin: journalctl
bin: logger
tag: system tag: system
tag: logs
aim: Convert markdown table to csv aim: Convert markdown table to csv
cmd: mlr --imarkdown --ocsv cat ${file}.md cmd: mlr --imarkdown --ocsv cat ${file}.md
@@ -218,8 +247,8 @@ cmd: grep -o "\b${word}\b" ${file}
bin: grep bin: grep
tag: search tag: search
aim: Reformat variable for shell input aim: Reformat text for shell input
cmd: printf "%q\n" "${variable}" cmd: printf "%q\n" "${text}"
bin: printf bin: printf
tag: xargs tag: xargs
tag: stdout tag: stdout
@@ -429,6 +458,13 @@ cmd: urldecode() { echo -e "${@//%/\\x}"; }
tag: web tag: web
shell: bash shell: bash
aim: Choose which parts to commit with git
cmd: git commit -p
note: Use `P` to see big changes which cannot fit on the screen.
tag: comfy
bin: git
shell: sh
aim: Request a definition from the terminal. aim: Request a definition from the terminal.
cmd: word='abderian' cmd: word='abderian'
+ curl -s dict://dict.org/define:${word}: + curl -s dict://dict.org/define:${word}:

View File

@@ -1,5 +1,5 @@
--- ---
title: Edit gpg encrypted files easily title: Edit gpg encrypted files with vim
tags: tags:
- vim - vim
- data - data

View File

@@ -1,5 +1,5 @@
--- ---
title: pdf to txt title: Convert a scanned pdf to text
tags: tags:
- data - data
- pdf - pdf

View File

@@ -16,23 +16,23 @@ Make a database for your boardgames, specifying only one field and value:
database=games.rec database=games.rec
n=Name n=Name
g=Vojvodina g=Vojvodina
touch $database touch ${database}
recins -f $n --value $g $database recins -f ${n} --value ${g} ${database}
recsel $database recsel ${database}
``` ```
Insert a few more, with the estimated playtime: Insert a few more, with the estimated playtime:
```sh ```sh
recins -f Name -v Saboter -f Playtime -v 30 $database recins -f Name -v Saboter -f Playtime -v 30 ${database}
recins -f Name -v Chess -f Playtime -v 30 $database recins -f Name -v Chess -f Playtime -v 30 ${database}
``` ```
View all games, or select one by number: View all games, or select one by number:
```sh ```sh
recsel $database recsel ${database}
recsel -n 0 $database recsel -n 0 ${database}
``` ```
Each game should note whether or not you have played it yet, so you can add that field and set the default to `yes`. Each game should note whether or not you have played it yet, so you can add that field and set the default to `yes`.
@@ -40,14 +40,14 @@ Each game should note whether or not you have played it yet, so you can add that
```sh ```sh
f=played f=played
v=yes v=yes
recset -f $f -a $v $database recset -f ${f} -a ${v} ${database}
``` ```
...but the field is wrong, it should have a capital letter: ...but the field is wrong, it should have a capital letter:
```sh ```sh
new_field=Played new_field=Played
recset -f $f --rename $new_field recset -f ${f} --rename ${new_field}
``` ```
## Read ## Read
@@ -55,20 +55,20 @@ recset -f $f --rename $new_field
Check how many records the database has: Check how many records the database has:
```sh ```sh
recinf $database recinf ${database}
``` ```
Look at just the games you've never played: Look at just the games you've never played:
```sh ```sh
recsel --expression="Played = 'no'" $database recsel --expression="Played = 'no'" ${database}
``` ```
Print how many, then just print the names: Print how many, then just print the names:
```sh ```sh
recsel -e "Played = 'no'" --count $database recsel -e "Played = 'no'" --count ${database}
recsel -e "Played = 'no'" --print=Name $database recsel -e "Played = 'no'" --print=Name ${database}
``` ```
## Update ## Update
@@ -79,8 +79,8 @@ To change a game's `Played` field from `no` to `yes`, use `recset` to specify th
num=0 num=0
f=Played f=Played
value=yes value=yes
recsel --number=$num $database recsel --number=${num} ${database}
recset --number=$num -f $f --set=$value $database recset --number=${num} -f ${f} --set=${value} ${database}
``` ```
Find all games with a playtime of `30`, and set the field `Max_Players` to `4`. Find all games with a playtime of `30`, and set the field `Max_Players` to `4`.
@@ -102,22 +102,22 @@ Remove `Played` record from first game:
```sh ```sh
num=0 num=0
recset --number=$num -f Played --delete $database recset --number=${num} -f Played --delete ${database}
``` ```
You can comment the line instead of deleting it: You can comment the line instead of deleting it:
```sh ```sh
num=1 num=1
recset --number=$num -f Played --delete $database recset --number=${num} -f Played --delete ${database}
recsel $database recsel ${database}
cat $database cat ${database}
``` ```
Delete an entire record: Delete an entire record:
```sh ```sh
num=2 num=2
recdel --number=$num $database recdel --number=${num} ${database}
``` ```

View File

@@ -9,8 +9,6 @@ requires:
- writing/vim.md - writing/vim.md
--- ---
- [Sample file](sc-im/sample.sc)
# Basic Commands # Basic Commands
## See Cells ## See Cells

View File

@@ -1,8 +1,10 @@
--- ---
title: Ach Linux GPU Setup title: Arch Linux GPU Setup
tags: tags:
- arch - arch
- GPU - GPU
requires:
- distros/arch/install_yay.md
--- ---
# Step 1: Multilib # Step 1: Multilib

View File

@@ -54,9 +54,8 @@ brightnessctl s 10%-
brightnessctl s 10%+ brightnessctl s 10%+
``` ```
# Other Tricks # Related
- [autologin](autologin.md) - [autologin](distros/void/autologin.md)
- [services](sv.md) - [services](distros/void/sv.md)
- [wifi](networking/wpa_supplicant.md)

View File

@@ -83,7 +83,7 @@ content: # This data file was generated by the Spreadsheet Calculator Improvised
filename: lowdown.mk filename: lowdown.mk
bin: make bin: make
usage: {{bin}} -f {{filename}} usage: {{bin}} -f {{filename}} example
content: output: all content: output: all
+ +
+ .PHONY: example + .PHONY: example
@@ -120,3 +120,36 @@ content: output: all
+ +
+ clean : + clean :
+ rm -rf public html + rm -rf public html
filename: Makefile
bin: make
usage: make
content: ### Variables
+
+ PAGER ?= $(shell command -v mdless bat less | head -1 )
+ EDITOR ?= vi
+
+ requirements += lowdown
+
+ ### Dependencies
+
+ out: help
+
+ ### Patterns
+
+
+ ### Phonies
+
+ .PHONY: help
+ help:
+ @awk 'BEGIN {FS = ":.*?## "} /^[0-9a-zA-Z._-]+:.*?## / {printf "\033[36m%s\033[0m : %s\n", $$1, $$2}' $(MAKEFILE_LIST) | \
+ sort | \
+ column -s ':' -t
+
+ .PHONY: check
+ check: ## Check you have the required dependencies
+ @$(foreach dep, $(requirements), type $(dep) >/dev/null || echo "Install $(dep)." ; )
+
+ .PHONY: clean
+ clean: ## Remove generated files.
+ $(RM) $(defaults)

View File

@@ -12,7 +12,7 @@ tags:
| CNAME | Alternative Address | "$domain".rs, "$subdomain.$domain".com | | CNAME | Alternative Address | "$domain".rs, "$subdomain.$domain".com |
| NS | Nameserver | ns1.fastname.com | | NS | Nameserver | ns1.fastname.com |
| MX | Email server | "$domain".com | | MX | Email server | "$domain".com |
| TXT | Literally anything,including ownership of a domain | - | | TXT | Literally anything | "drunk giraffes can't spell" |
Query a host's IP and email handlers with the `host` command. Query a host's IP and email handlers with the `host` command.

22
networking/stop_email.md Normal file
View File

@@ -0,0 +1,22 @@
---
title: Stop email impersonating your domain
tags:
- networking
requires:
- networking/dns_records.md
---
There is nothing to stop scammers from sending email claiming to be coming from your domain.
And the older it gets, the more valuable it is for spoofing.
Just add these two TXT records to the DNS for your domain:
Name | Type | Value
:------|:----:|:-----
@ | TXT | v=spf1 -all
_dmarc | TXT | v=DMARC1; p=reject;
The first says there is not a single SMTP server on earth authorized to send email on behalf of your domain.
The second says that any email that says otherwise should be trashed.

70
shell/bash_tips.md Normal file
View File

@@ -0,0 +1,70 @@
---
title: Bash tips
tags:
- shell
- comfy
- bash
---
# This & That
Refer to 'that last thing', and 'the first thing':
```sh
fortune -l > file1
cat !$ | tr -d u > file2
cat file1 !$
diff !^ !$
```
**NB:** this can go wrong:
```sh
ls -l file1 file2
cat !^
```
**NB:** this only works when running `bash` interactively, never in scripts.
# Lists
You can put a list inside any `bash` argument, and `bash` will expand that part into a new argument.
```bash
echo file {one,two,three}.txt
echo file-{one,two,three}.txt
touch !$
```
Look at text files:
```bash
ls *.{txt,md}
```
Look at size of jpg or png files in the `img/` directory:
```bash
du img/*.{jpg,png}
```
# Automatic Lists
```bash
echo {a..d}
echo Archive_{B..E}
```
Using multiple lists works fine.
```bash
mkdir first second third
echo {first,second,third}/file_{1..3}.txt
x={first,second,third}/file_{1..3}.txt
echo $x
echo {first,second,third}/file_{1..3}.txt
x="$(!!)"
echo $x
for file in $x ; do fortune > $file ; done
```

View File

@@ -46,5 +46,5 @@ Just press `!`, e.g. `!ls`.
# Edit a File # Edit a File
While reading a file, press `v` to edit it ('v' stands of `vi`). While reading a file, press `v` to edit it ('v' stands for `vi`).

View File

@@ -5,25 +5,6 @@ tags:
- comfy - comfy
--- ---
# This & That
Refer to 'that last thing', and 'the first thing':
```sh
fortune -l > file1
cat !$ | tr -d u
diff !^ !$
```
**NB:** this can go wrong:
```sh
ls -l file1 file2
cat !^
```
**NB:** this only works when running `bash` interactively, never in scripts.
# Done # Done
`<C-d>` `<C-d>`

View File

@@ -1,25 +1,25 @@
--- ---
title: $EDITOR title: Setting an EDITOR
tags: tags:
- system - system
- defaults
--- ---
The System's default text editor can be defined within /etc/profile. It's given the variable `EDITOR`.
Add these lines to `/etc/profile.d/custom.sh`: Programs expect a default 'line EDITOR' and 'VISUAL editor' so they know how you want to edit text.
Add these lines to automatically set the variables in `bash`:
```sh ```sh
echo 'export EDITOR=vim' >> /etc/profile.d/custom.sh echo 'export EDITOR=vim' >> ~/.bashrc
echo 'export VISUAL=$EDITOR' >> /etc/profile.d/custom.sh echo 'export VISUAL=$EDITOR' >> ~/.bashrc
``` ```
Then reload that profile with: Make the change system-wide by adding them to `/etc/profile.d/custom.sh` instead, which is loaded at startup.
You can add a GUI editor as the `$VISUAL` editor:
```sh ```sh
source /etc/profile VISUAL=gedit
``` ```
If you want to ensure `nano` never appears again: To use a true line editor, as `$EDITOR`, see [ed][writing/ed.md].
```sh
sudo ln -sf $(which vim) $(which nano)
```

View File

@@ -180,6 +180,6 @@ In this case, the makefile can see that `backup` depends on the current backup f
# The Rest # The Rest
- [File patterns](makefiles/patterns.md) - [File patterns](system/makefiles/patterns.md)
- [Makefile graphs](makefiles/graph-easy.md) - [Makefile graphs](system/makefiles/graph-easy.md)
- [In-build help](makefiles/help.md) - [In-build help](system/makefiles/help.md)

View File

@@ -24,11 +24,11 @@ Note the asterisk marking the boot partition.
# IDs # IDs
| ID | Meaning | | ID | Meaning |
|----|:--------| |:----------:|:-----------|
|83 |Linux | | 83 | Linux |
| 5 |Extended | | 5 | Extended |
| 82 |Swap | | 82 | Swap |
fdisk will not help with a GPT formatted drive. For this, use gdisk, which is mostly the same. fdisk will not help with a GPT formatted drive. For this, use gdisk, which is mostly the same.
@@ -52,15 +52,15 @@ mkreiserfs /dev/sdc2
# File System Types # File System Types
| Type | Advantages | Disadvantages | | Type | Advantages | Disadvantages |
|------|:-----------|:--------------| |----------------|:----------------------------------------------|:-------------------------------------------------------------|
|ext2 | |No journaling means that the file offers no crash recovery. | ext2 | | No journaling means that the file offers no crash recovery. |
|ext3 | Journaling | | ext3 | Journaling | |
|ext4 | Journaling and handles files of up to 16TB.| | ext4 | Journaling and handles files of up to 16TB. | |
|reiserfs| Journalin and stable.| | reiserfs | Journalin and stable. | |
|btrfs |Reliable and stable| | btrfs | Reliable and stable | |
|XFS |Journaling, great for large files.| | XFS | Journaling, great for large files. | |
|VFAT |Comptable with Windows, like FAT32| | VFAT | Comptable with Windows, like FAT32 | |
# Parted # Parted

View File

@@ -13,23 +13,23 @@ Input a command with C-b
In addition to Windows, there are panes. In addition to Windows, there are panes.
|Commands | Key | |Commands | Key |
| ---- | ---- | |------------------|------|
| New Window | c | | New Window | c |
| Previous Window | p | | Previous Window | p |
| next window | n | | next window | n |
| list windows | w | | list windows | w |
| vertical split | % | | vertical split | % |
| horizontal split | " | | horizontal split | " |
| name a command | : | | name a command | : |
| kill pane | x | | kill pane | x |
| kill session | d | | kill session | d |
|Name Commands| ### Name Commands
| --------|
| split-window | - split-window
| rename-window | - rename-window
# Sessions # Sessions

View File

@@ -12,14 +12,6 @@ Turn a markdown file into a pdf:
lowdown -stms "$FILE".md | pdfroff -itk -mspdf > "$FILE".pdf lowdown -stms "$FILE".md | pdfroff -itk -mspdf > "$FILE".pdf
``` ```
*Example:* put [this Makefile](lowdown/example.txt) in a directory, rename it `Makefile`, then do:
```sh
make example
make
```
To give the document a title, put that title in the metadata: To give the document a title, put that title in the metadata:
```sh ```sh

View File

@@ -3,8 +3,13 @@ title: Ed: The Standard Editor
tags: tags:
- writing - writing
- guide - guide
- sed
- vim
--- ---
Understanding `ed` will let you understand all that feels strange about the system.
It set the standards for `sed` and `vi`.
`ed` was designed for real terminals, i.e. a typewriter. `ed` was designed for real terminals, i.e. a typewriter.
You would type a command to the computer, and it would type out any errors. You would type a command to the computer, and it would type out any errors.
It would not waste paper, ink, and time by typing out `COMMAND RUN SUCCESSFULLY` after each command. It would not waste paper, ink, and time by typing out `COMMAND RUN SUCCESSFULLY` after each command.
@@ -12,7 +17,6 @@ A silent machine meant a happy machine.
To fully appreciate `ed`, you can slow down your terminal with the following command: To fully appreciate `ed`, you can slow down your terminal with the following command:
```sh ```sh
ff=/tmp/bashpipe ff=/tmp/bashpipe
mkfifo $ff mkfifo $ff
@@ -24,7 +28,6 @@ Try running `dir` and `dir -F`!
Okay, now onto `ed`... Okay, now onto `ed`...
# Basic Usage # Basic Usage
Open a file: Open a file:
@@ -67,11 +70,8 @@ Delete the current line:
d d
``` ```
Write the 'buffer' to disk: Write the 'buffer' to disk:
```ed ```ed
w w
``` ```
@@ -86,7 +86,6 @@ q
Open that file: Open that file:
```ed ```ed
ed file.md ed file.md
``` ```

View File

@@ -20,8 +20,9 @@ Keybind to exit this mode is `Ctrl+q`
## Extras ## Extras
- [Learning Vim](vim/vi.md) - [Learning Vim](writing/vim/vi.md)
- [Navigation](vim/navigate.md) - [Navigation](writing/vim/navigate.md)
- [Completion](vim/completion.md) - [Completion](writing/vim/completion.md)
- [Window Splits](vim/windows.md) - [Window Splits](writing/vim/windows.md)
- [Use vim bindings in bash](vim/vim_in_bash.md) - [Use vim bindings in bash](writing/vim/vim_in_bash.md)
- [A game to learn how to code in Vim](https://www.vim-hero.com/)

116
writing/vim/csv_to_md.md Normal file
View File

@@ -0,0 +1,116 @@
---
title: CSV to Markdown in Vim
tags:
- writing
- vim
- csv
- markdown
requires:
- writing/vim.md
---
Open a CSV table (I made this one with `:r!sed 's/:/,/g' /etc/passwd | head`).
```csv
root,x,0,0,,/root,/bin/bash
bin,x,1,1,,/,/usr/bin/nologin
daemon,x,2,2,,/,/usr/bin/nologin
mail,x,8,12,,/var/spool/mail,/usr/bin/nologin
ftp,x,14,11,,/srv/ftp,/usr/bin/nologin
http,x,33,33,,/srv/http,/usr/bin/nologin
nobody,x,65534,65534,Nobody,/,/usr/bin/nologin
dbus,x,81,81,System Message Bus,/,/usr/bin/nologin
systemd-coredump,x,981,981,systemd Core Dumper,/,/usr/bin/nologin
systemd-network,x,980,980,systemd Network Management,/,/usr/bin/nologin
```
Highlight the table.
- Go to the top, with 'root'.
- Type `V9j`.
- `:!column -ts, -o '|'`
- Return!
```csv
root |x|0 |0 | |/root |/bin/bash
bin |x|1 |1 | |/ |/usr/bin/nologin
daemon |x|2 |2 | |/ |/usr/bin/nologin
mail |x|8 |12 | |/var/spool/mail|/usr/bin/nologin
ftp |x|14 |11 | |/srv/ftp |/usr/bin/nologin
http |x|33 |33 | |/srv/http |/usr/bin/nologin
nobody |x|65534|65534|Nobody |/ |/usr/bin/nologin
dbus |x|81 |81 |System Message Bus |/ |/usr/bin/nologin
systemd-coredump|x|981 |981 |systemd Core Dumper |/ |/usr/bin/nologin
systemd-network |x|980 |980 |systemd Network Management|/ |/usr/bin/nologin
```
The command displays as `:'<,'>!column -ts, -o '|'`.
This looks better, but the spacing is bad because the output separate is `-o '|'`.
You can put spaces around that pipe by making the separator a pipe (`-s'|'`)
and making the output separator a pipe with spaces (`-o' | '`).
```vim
:'<,'>!column -ts'|' -o ' | '
```
```csv
root | x | 0 | 0 | | /root | /bin/bash
bin | x | 1 | 1 | | / | /usr/bin/nologin
daemon | x | 2 | 2 | | / | /usr/bin/nologin
mail | x | 8 | 12 | | /var/spool/mail | /usr/bin/nologin
ftp | x | 14 | 11 | | /srv/ftp | /usr/bin/nologin
http | x | 33 | 33 | | /srv/http | /usr/bin/nologin
nobody | x | 65534 | 65534 | Nobody | / | /usr/bin/nologin
dbus | x | 81 | 81 | System Message Bus | / | /usr/bin/nologin
systemd-coredump | x | 981 | 981 | systemd Core Dumper | / | /usr/bin/nologin
systemd-network | x | 980 | 980 | systemd Network Management | / | /usr/bin/nologin
```
Make a header by copying the top line and replacing text (`yypkR`).
That's nicer, but the formatting's wrong again.
```markdown
User | Passwords | UID | GID | Description | Home | Shell
root | x | 0 | 0 | | /root | /bin/bash
[...]
```
Time to fix it with `:'<,'>!column -ts'|' -o'|'`.
```csv
User | Passwords | UID | GID | Description | Home | Shell
----------------- | ----------- | ------- | ------- | ---------------------------- | ----------------- | ----------
root | x | 0 | 0 | | /root | /bin/bash
bin | x | 1 | 1 | | / | /usr/bin/nologin
daemon | x | 2 | 2 | | / | /usr/bin/nologin
mail | x | 8 | 12 | | /var/spool/mail | /usr/bin/nologin
ftp | x | 14 | 11 | | /srv/ftp | /usr/bin/nologin
http | x | 33 | 33 | | /srv/http | /usr/bin/nologin
nobody | x | 65534 | 65534 | Nobody | / | /usr/bin/nologin
dbus | x | 81 | 81 | System Message Bus | / | /usr/bin/nologin
systemd-coredump | x | 981 | 981 | systemd Core Dumper | / | /usr/bin/nologin
systemd-network | x | 980 | 980 | systemd Network Management | / | /usr/bin/nologin
```
Now we just need the spacer line.
Copy the top line (`yyp`) and replace (`:s/not-pipe/-/g`).
You can say 'not the pipe symbol' with `[^|]` or 'not-pipe-or-colon' with `[^:|]`.
```vim
:s/[^:|]/-/g
```
# Keyboard Shortcut
Put this in your `~/.vimrc` to map 'Control + s' to reformat CSV while in visual mode.
```vim
vmap <C-s> :!column -ts, -o " \| "<Enter>yyp:s/[^\|:]/-/g<Enter>
```

82
writing/vim/format_md.md Normal file
View File

@@ -0,0 +1,82 @@
---
title: Reformat a Markdown Table
tags:
- writing
- vim
- markdown
requires:
- writing/vim.md
---
This markdown table is badly messed up:
```markdown
| File | Category |
|:------|:---------|
| calendar.md | tex|
| tex_packages.md | tex|
| completion.md | vim|
| csv_to_md.md | vim|
| format_md.md | vim|
```
Highight from the top with `V6j`, then run `column` to fix the output:
```vim
:!column -ts'|' -o '|'
```
It displays like this:
```vim
:'<,'>!column -ts'|' -o '|'
```
```markdown
| File | Category |
|:------ |:---------|
| calendar.md | tex |
| tex_packages.md | tex |
| completion.md | vim |
| csv_to_md.md | vim |
| format_md.md | vim |
```
That's better, but the header is broken.
Fix is by replacing spaces with dashes.
```vim
:s/ /-/g
```
The lines have too much whitespace.
You can fix this with the 'truncate' command, to squeeze repeating spaces or dashes.
```vim
tr -s ' -' |column -ts '|' -o '|'
```
```markdown
| File | Category |
|:----------------|:---------|
| calendar.md | tex |
| tex_packages.md | tex |
| completion.md | vim |
| csv_to_md.md | vim |
| format_md.md | vim |
```
# Keyboard Shortcut
Put this in your `~/.vimrc` to map 'Control + t' to reformat markdown tables in visual mode.
```vim
vmap <C-t> :!tr -s ' -' \|column -ts '\|' -o '\|'<Enter>j:s/ /-/g<Enter>k
```