Compare commits
11 Commits
2d95304da4
...
c407e8be9e
Author | SHA1 | Date | |
---|---|---|---|
c407e8be9e
|
|||
f52b241dc2
|
|||
c0755da29f
|
|||
c3afb4b562
|
|||
f5b3d969fd
|
|||
7e2487f0d3
|
|||
3fec180a14
|
|||
c08ad6f175
|
|||
1a17ffda7f
|
|||
556dba6f29
|
|||
b7a79951c5
|
@@ -44,6 +44,8 @@ They should not assume the reader knows much beyond common terminal commands, an
|
|||||||
People should be able to read an article from the beginning, then keep going until the end, and then stop.
|
People should be able to read an article from the beginning, then keep going until the end, and then stop.
|
||||||
Articles should not take a detour through a chain of other articles of unknown size.
|
Articles should not take a detour through a chain of other articles of unknown size.
|
||||||
|
|
||||||
|
[Do not Jaquays documentation](https://splint.rs/posts/no_links)
|
||||||
|
|
||||||
## Be Opinionated
|
## Be Opinionated
|
||||||
|
|
||||||
- Guides should not ask the reader to select options half-way through.
|
- Guides should not ask the reader to select options half-way through.
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
---
|
---
|
||||||
title: "git-lfs"
|
title: "git-lfs"
|
||||||
tags: [ "data", "git" ]
|
tags: [ "data", "git" ]
|
||||||
|
requires: [ "git" ]
|
||||||
---
|
---
|
||||||
|
|
||||||
Git Large File Storage ('LFS') needs to change your `~/.gitconfig` to check out those binary files:
|
Git Large File Storage ('LFS') needs to change your `~/.gitconfig` to check out those binary files:
|
||||||
|
69
data/git/git_stash.md
Normal file
69
data/git/git_stash.md
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
---
|
||||||
|
title: "git stash"
|
||||||
|
tags: [ "data", "git" ]
|
||||||
|
requires: [ "git" ]
|
||||||
|
---
|
||||||
|
|
||||||
|
Save file-changes without committing anything.
|
||||||
|
|
||||||
|
Change a file:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
file=README.md
|
||||||
|
fortune >> ${file}
|
||||||
|
git diff
|
||||||
|
git stash save
|
||||||
|
```
|
||||||
|
|
||||||
|
List which stashes you have:
|
||||||
|
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git stash list
|
||||||
|
|
||||||
|
stash@{1}: WIP on master: c21f102 init git
|
||||||
|
```
|
||||||
|
|
||||||
|
Make a new file, then stash it:
|
||||||
|
|
||||||
|
|
||||||
|
```sh
|
||||||
|
otherfile=file.log
|
||||||
|
fortune > ${otherfile}
|
||||||
|
git add ${otherfile}
|
||||||
|
stashname=logfile
|
||||||
|
git stash save ${stashname}
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you can see two stashed changes, and the most recent has a name:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git stash list
|
||||||
|
|
||||||
|
stash@{0}: On master: logfile
|
||||||
|
stash@{1}: WIP on master: c21f102 init git
|
||||||
|
```
|
||||||
|
|
||||||
|
You can delete a stash by referring to its index number, or name (if it has one).
|
||||||
|
|
||||||
|
```sh
|
||||||
|
choice=1
|
||||||
|
git stash drop ${choice}
|
||||||
|
|
||||||
|
choice=${stashname}
|
||||||
|
git stash drop ${choice}
|
||||||
|
```
|
||||||
|
|
||||||
|
Or just run `git stash drop` to remove the most recent (labelled `{0}`).
|
||||||
|
|
||||||
|
Return stashed changes with an index number (or the most recent).
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git stash pop ${choice}
|
||||||
|
```
|
||||||
|
|
||||||
|
Delete all stashes:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git stash clear
|
||||||
|
```
|
34
data/task/contexts.md
Normal file
34
data/task/contexts.md
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
title: "Taskwarrior Contexts"
|
||||||
|
tags: [ "data", "task" ]
|
||||||
|
requires: [ "Taskwarrior" ]
|
||||||
|
---
|
||||||
|
|
||||||
|
# Contexts
|
||||||
|
|
||||||
|
Set three contexts by their tags:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
task context define work +sa or +hr
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
task context define study +ed or +void or +rat
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
task context define home -sa -hr -ed -void -rat
|
||||||
|
```
|
||||||
|
|
||||||
|
Change to the first context.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
task context work
|
||||||
|
```
|
||||||
|
|
||||||
|
Then stop.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
task context none
|
||||||
|
```
|
||||||
|
|
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: "task"
|
title: "Taskwarrior"
|
||||||
tags: [ "organization" ]
|
tags: [ "data", "organization" ]
|
||||||
---
|
---
|
||||||
|
|
||||||
Set up the configuration file:
|
Set up the configuration file:
|
||||||
@@ -9,6 +9,18 @@ Set up the configuration file:
|
|||||||
task
|
task
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Taskwarrior published a new feature to synchronize tasks others, but the feature was not ready.
|
||||||
|
The server's default installation instructions assume that users pay for hosting services.
|
||||||
|
All listed providers run proprietary software and actively support genocide.
|
||||||
|
|
||||||
|
|
||||||
|
To ignore the synchronization, tell the configuration file to use a local synchronization file.
|
||||||
|
|
||||||
|
```
|
||||||
|
task config sync.local.server_dir
|
||||||
|
task config data.location ~/.local/state/
|
||||||
|
```
|
||||||
|
|
||||||
Add a task:
|
Add a task:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
@@ -44,18 +56,16 @@ task add project:house buy potted plant
|
|||||||
task add proj:house.repair buy screwdriver
|
task add proj:house.repair buy screwdriver
|
||||||
task add proj:house.repair buy shelf brackets
|
task add proj:house.repair buy shelf brackets
|
||||||
task add pro:house.paint buy white paint
|
task add pro:house.paint buy white paint
|
||||||
task add pro:house.paint buy red paint
|
|
||||||
task add pro:house.paint buy black paint
|
for t in "buy red paint" "buy black paint" "buy brushes" ; do
|
||||||
task add pro:house.paint buy brushes
|
task add pro:house.paint $t
|
||||||
|
done
|
||||||
```
|
```
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
task pro:house sum
|
task pro:house sum
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
task burndown.daily pro:house
|
task burndown.daily pro:house
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -63,44 +73,12 @@ The summaries will show how fast a project is being completed, and when you can
|
|||||||
|
|
||||||
# Tags
|
# Tags
|
||||||
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
task add +buy toothbrush
|
task add +buy toothbrush
|
||||||
```
|
|
||||||
|
|
||||||
You can then see only tasks which involve buying something with:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
task +buy
|
task +buy
|
||||||
```
|
```
|
||||||
|
|
||||||
# Contexts
|
|
||||||
|
|
||||||
Set three contexts by their tags:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
task context define work +sa or +hr
|
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
task context define study +ed or +void or +rat
|
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
task context define home -sa -hr -ed -void -rat
|
|
||||||
```
|
|
||||||
|
|
||||||
Change to the first context.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
task context work
|
|
||||||
```
|
|
||||||
|
|
||||||
Then stop.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
task context none
|
|
||||||
```
|
|
||||||
|
|
||||||
# Review
|
# Review
|
||||||
|
|
||||||
View list of tasks completed in the last week:
|
View list of tasks completed in the last week:
|
||||||
@@ -111,21 +89,17 @@ task end.after:today-1wk completed
|
|||||||
|
|
||||||
# User Defined Attributes
|
# User Defined Attributes
|
||||||
|
|
||||||
Make a UDA 'size'.
|
Define a new attribute for tasks called 'size'.
|
||||||
|
The 'user defined attribute' (UDA) needs a `type` and `label`.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
task config uda.size.type string
|
task config uda.size.type string
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
task config uda.size.label Size
|
task config uda.size.label Size
|
||||||
```
|
```
|
||||||
|
You can also ensure task tasks can only be `large`, `medium`, or `small`, then set a default.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
task config uda.size.values large,medium,small
|
task config uda.size.values large,medium,small
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
uda.size.default=medium
|
uda.size.default=medium
|
||||||
```
|
```
|
||||||
|
|
20
data/task/taskwarrior_configuration.md
Normal file
20
data/task/taskwarrior_configuration.md
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
title: "Taskwarrior Configuration"
|
||||||
|
tags: [ "data", "task" ]
|
||||||
|
requires: [ "Taskwarrior" ]
|
||||||
|
---
|
||||||
|
|
||||||
|
Show your current config:
|
||||||
|
|
||||||
|
|
||||||
|
```sh
|
||||||
|
task show
|
||||||
|
```
|
||||||
|
|
||||||
|
Use machine-readable output to make a config file with all configuration keys shown, then make it your configuration file.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
task _show > ${file}
|
||||||
|
mv ${file} ~/.config/task/taskrc
|
||||||
|
```
|
||||||
|
|
25
networking/port_scan.md
Normal file
25
networking/port_scan.md
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
title: "Port Scan"
|
||||||
|
tags: [ "networking" ]
|
||||||
|
repo: 'https://github.com/mrjackwills/havn/'
|
||||||
|
---
|
||||||
|
|
||||||
|
`havn` scans ports.
|
||||||
|
It's not in many repos, but if you can `cargo install havn`.
|
||||||
|
|
||||||
|
|
||||||
|
```sh
|
||||||
|
havn -h
|
||||||
|
havn -a
|
||||||
|
domain=splint.rs
|
||||||
|
havn -p 19-90 ${domain}
|
||||||
|
```
|
||||||
|
|
||||||
|
That last command doesn't work reliably, so increase the number of retries (`-r`), or decrease concurrent requests (`-c`).
|
||||||
|
|
||||||
|
|
||||||
|
```sh
|
||||||
|
havn -p 19-443 -r 6 ${domain}
|
||||||
|
havn -p 1-1000 -c 500 -r 5 ${domain}
|
||||||
|
```
|
||||||
|
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
title: "Makefile Patterns"
|
title: "Makefile Patterns"
|
||||||
tags: [ "system", "make" ]
|
tags: [ "system", "make" ]
|
||||||
|
98
system/Makefiles/python_projects.md
Normal file
98
system/Makefiles/python_projects.md
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
---
|
||||||
|
title: "Python Projects with Makefiles"
|
||||||
|
tags: [ "tutorial", "system", "makefiles", "graphviz", "python" ]
|
||||||
|
requires: [ "Makefiles" ]
|
||||||
|
---
|
||||||
|
|
||||||
|
If you have a python script which requires a packages - e.g. `graphviz` - you can automate the setup with a `Makefile`.
|
||||||
|
The `Makefile` will:
|
||||||
|
|
||||||
|
1. Make three copies of an 8-line installer script.
|
||||||
|
2. Use one of the installer script to install local packages.
|
||||||
|
3. Install a symbolic link to python.
|
||||||
|
3. Make a script called `activate`, which tells python to use
|
||||||
|
|
||||||
|
# Context
|
||||||
|
|
||||||
|
Python coders don't like updating their projects, they just expect everyone to install the same version of everything that they have.
|
||||||
|
Historically, people dealt with this by installing only half a dozen copies of `graphviz`; but now each python project uses a local environment, with a local copy of `graphviz`, which means everyone gets to install a new copy of `graphviz` every time they try out a project.
|
||||||
|
|
||||||
|
Downloading 40MB of software for each 40-line script you write is called 'virtual environments' because it sounds cool.
|
||||||
|
We can make it even cooler with `make`, but not yet, because python - like the fae of old - will not fetch anything until you know its true name.
|
||||||
|
|
||||||
|
# Setup
|
||||||
|
|
||||||
|
```sh
|
||||||
|
command -v python
|
||||||
|
realpath `!!`
|
||||||
|
```
|
||||||
|
|
||||||
|
You must reveal that true path, because `python` is always a relative symbolic link, to an absolute symbolic link, which leads to a shortcut.
|
||||||
|
We can finally let `make` know how to invoke python, and where it will install `graphviz`.
|
||||||
|
|
||||||
|
If your python's version is '3.14', then python needs its packages placed in `${somewhere}/lib/python3.14/site-packages/`.
|
||||||
|
You must create a new, local, name for these packages, because - like the fey of old - python demands a private name in return for revealing its true name.
|
||||||
|
|
||||||
|
I'll call mine `camelot`, because the path is long and arduous.
|
||||||
|
Set up the Makefiles like this:
|
||||||
|
|
||||||
|
```make
|
||||||
|
py_link != command -v python
|
||||||
|
py != realpath $(py_link)
|
||||||
|
version != basename $(py)
|
||||||
|
|
||||||
|
virtenv = camelot
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you can ask for a local `pip` script, which can install the python packages:
|
||||||
|
|
||||||
|
```make
|
||||||
|
[...]
|
||||||
|
|
||||||
|
$(virtenv)/bin/pip:
|
||||||
|
$(py) -m venv $(virtenv)
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, list the packages you want in `requirements.txt`, and make `pip` install from it.
|
||||||
|
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ppkg=graphviz
|
||||||
|
echo ${ppkg} > requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
```make
|
||||||
|
[...]
|
||||||
|
|
||||||
|
pkgs = $(virtenv)/lib/$(version)/site-packages/
|
||||||
|
|
||||||
|
$(pkgs): $(virtenv)/bin/pip
|
||||||
|
$(pkgs): requirements.txt
|
||||||
|
$(virtenv)/bin/pip install -r $<
|
||||||
|
```
|
||||||
|
|
||||||
|
The complete Makefile looks like this:
|
||||||
|
|
||||||
|
|
||||||
|
```make
|
||||||
|
all: .default
|
||||||
|
|
||||||
|
py_link != command -v python
|
||||||
|
py != realpath $(py_link)
|
||||||
|
version != basename $(py)
|
||||||
|
|
||||||
|
virtenv = camelot
|
||||||
|
|
||||||
|
$(virtenv)/bin/pip:
|
||||||
|
$(py) -m venv $(virtenv)
|
||||||
|
|
||||||
|
pkgs = $(virtenv)/lib/$(version)/site-packages/
|
||||||
|
|
||||||
|
$(pkgs): $(virtenv)/bin/pip
|
||||||
|
$(pkgs): requirements.txt
|
||||||
|
$(virtenv)/bin/pip install -r $<
|
||||||
|
|
||||||
|
.PHONY: .default
|
||||||
|
.default: $(pkgs)
|
||||||
|
```
|
||||||
|
|
@@ -10,7 +10,7 @@ ffmpeg -i [input file] output_file.mkv
|
|||||||
|
|
||||||
The input file might be a device, such as a camera.
|
The input file might be a device, such as a camera.
|
||||||
|
|
||||||
#Record screen
|
# Record screen
|
||||||
|
|
||||||
Take the format as 'grab the x11 screen'.
|
Take the format as 'grab the x11 screen'.
|
||||||
|
|
||||||
@@ -30,7 +30,8 @@ or maybe just...
|
|||||||
ffmpeg -f x11grab -s "$(xdpyinfo | grep dimensions | awk '{print $2}')" -i :1.0 out.mkv
|
ffmpeg -f x11grab -s "$(xdpyinfo | grep dimensions | awk '{print $2}')" -i :1.0 out.mkv
|
||||||
```
|
```
|
||||||
|
|
||||||
#Add default pulse audio
|
# Add default pulse audio
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ffmpeg -f x11grab -s [screensize] -i :0.0 -f alsa -i default out.mkv
|
ffmpeg -f x11grab -s [screensize] -i :0.0 -f alsa -i default out.mkv
|
||||||
```
|
```
|
||||||
|
22
vision/make_a_gif.md
Normal file
22
vision/make_a_gif.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
title: "Make a gif"
|
||||||
|
tags: [ "vision" ]
|
||||||
|
---
|
||||||
|
|
||||||
|
Split your video into frames.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
d=$(mktemp -d)
|
||||||
|
cp $vid.mp4 $d
|
||||||
|
cd $d
|
||||||
|
|
||||||
|
ffmpeg -i $vid.mp4 -vf "fps=10, scale=360:-1" frame%04d.png
|
||||||
|
gifski --fps 10 -o ${out}.gif frame*.png
|
||||||
|
```
|
||||||
|
|
||||||
|
Optimize:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
gifsicle --optimize=3 --lossy=100 -o ${final}.gif ${out}.gif
|
||||||
|
```
|
||||||
|
|
12
writing/tex/calendar.md
Normal file
12
writing/tex/calendar.md
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
title: "Calendar"
|
||||||
|
tags: [ "writing", "tex", "fun" ]
|
||||||
|
requires: [ "LaTeX Packages" ]
|
||||||
|
---
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yplan $(date +%Y) > ${file}.tex
|
||||||
|
pdflatex -output-directory=/tmp/ ${file}.tex
|
||||||
|
mv /tmp/${file}.pdf .
|
||||||
|
```
|
||||||
|
|
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: "LaTeX Setup the Hard Way"
|
title: "LaTeX Packages"
|
||||||
tags: [ "writing" ]
|
tags: [ "writing" ]
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ ls /opt/texlive/${YEAR}/texmf-dist/scripts/texlive/tlmgr.pl
|
|||||||
```
|
```
|
||||||
|
|
||||||
Double-check the year.
|
Double-check the year.
|
||||||
It should *not* match the real year, it should match the `texlive`.
|
It should *not* match the current year, it should match the `texlive`.
|
||||||
|
|
||||||
## Problems along the Path
|
## Problems along the Path
|
||||||
|
|
@@ -3,13 +3,14 @@ title: "vim basics"
|
|||||||
tags: [ "vim", "basic" ]
|
tags: [ "vim", "basic" ]
|
||||||
---
|
---
|
||||||
|
|
||||||
1. Insert text by pressing `i`.
|
1. Insert text by pressing `a`.
|
||||||
1. Stop inserting text by pressing `Ctrl+[`.
|
1. Stop inserting text by pressing `Ctrl+[`.
|
||||||
1. Exit with `ZZ`.
|
1. Exit with `ZZ`.
|
||||||
1. Congratulations, you now know `vim`.
|
1. Congratulations, you now know `vim`.
|
||||||
|
|
||||||
## Extras
|
## Extras
|
||||||
|
|
||||||
|
- [Learning Vim](vim/vi.md)
|
||||||
- [Navigation](vim/navigate.md)
|
- [Navigation](vim/navigate.md)
|
||||||
- [Completion](vim/completion.md)
|
- [Completion](vim/completion.md)
|
||||||
- [Search](vim/search.md)
|
- [Search](vim/search.md)
|
||||||
|
46
writing/vim/vi.md
Normal file
46
writing/vim/vi.md
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
---
|
||||||
|
title: "How to Learn `vim`"
|
||||||
|
tags: [ "vim", "learning" ]
|
||||||
|
requires: [ "vim basics" ]
|
||||||
|
---
|
||||||
|
|
||||||
|
1. Uninstall `vim`.
|
||||||
|
1. Install `vi`.
|
||||||
|
1. Write a few blog posts.
|
||||||
|
|
||||||
|
The [ancient wisdom](https://stackoverflow.com/questions/1218390/what-is-your-most-productive-shortcut-with-vim/1220118#1220118) is correct - everyone should start with `vi`.
|
||||||
|
But the standard wisdom fails to mention writing.
|
||||||
|
So people just 'try to remember', then they edit a couple of configuration files with `vim`, then stop, because it's a pain to think about keystrokes while thinking about how the configuration file works.
|
||||||
|
Nobody can learn like that.
|
||||||
|
|
||||||
|
Learn with a blog, or writing emails in `vim`, or writing anything, as long as it's *real writing*.
|
||||||
|
Write a journal or some recipes.
|
||||||
|
Write literally anything which is written in paragraphs.
|
||||||
|
|
||||||
|
And while you're writing, remember one rule: if you want something, `vi` can do it, you just need to look up how.
|
||||||
|
|
||||||
|
Blog first, then try out some of these commands:
|
||||||
|
|
||||||
|
- `hjkl`
|
||||||
|
- `x`
|
||||||
|
- `:!grep very %`
|
||||||
|
- `onew line<Esc>...`
|
||||||
|
- `Onew line<Esc>...`
|
||||||
|
- `~`
|
||||||
|
- `~~~~`
|
||||||
|
- `$r!`
|
||||||
|
- `w %-2`
|
||||||
|
- `x!`
|
||||||
|
- `0RTipex`
|
||||||
|
- `_4rX`
|
||||||
|
- `bc2e`
|
||||||
|
- `c2E`
|
||||||
|
- `cw`
|
||||||
|
- `cW`
|
||||||
|
- `ci'`
|
||||||
|
- `zz`
|
||||||
|
- `:set number`
|
||||||
|
- `:set nonumber`
|
||||||
|
- `:set relativenumber`
|
||||||
|
- `:set number relativenumber`
|
||||||
|
|
Reference in New Issue
Block a user