Compare commits

..

96 Commits

Author SHA1 Message Date
Stefan Hagen
832cfe42c3 Update 2026-02-17 08:42 Darwin/arm64-GH2T6W9K6H 2026-02-17 09:09:14 +01:00
c0dev0id
bf213e469f Update 2026-01-26 20:34 OpenBSD/amd64-dalek 2026-01-26 20:35:00 +01:00
c0dev0id
0bd8a43d4f Update 2026-01-26 16:17 OpenBSD/amd64-dalek 2026-01-26 16:17:20 +01:00
c0dev0id
186dfa8096 Update 2026-01-25 09:38 OpenBSD/amd64-t14 2026-01-25 09:38:17 +01:00
c0dev0id
0769d7a789 Update 2026-01-17 09:55 OpenBSD/amd64-t14 2026-01-17 09:55:19 +01:00
c0dev0id
4dfd87462c Update 2025-12-13 14:50 OpenBSD/amd64-t14 2025-12-13 14:50:33 +01:00
c0dev0id
1cc3015bb5 Update 2025-09-29 07:50 OpenBSD/amd64-t14 2025-09-29 07:50:12 +02:00
c0dev0id
a3954fb9dc Update 2025-09-03 17:04 OpenBSD/amd64-t14 2025-09-03 17:04:32 +02:00
c0dev0id
a074d5b67d Update 2025-08-31 19:39 OpenBSD/amd64-t14 2025-08-31 19:39:39 +02:00
c0dev0id
ff04acca3a Update 2025-08-20 22:21 OpenBSD/amd64-t14 2025-08-20 22:21:12 +02:00
c0dev0id
6028f3a023 Update 2025-08-18 17:54 OpenBSD/amd64-t14 2025-08-18 17:54:24 +02:00
c0dev0id
9764ad6f1f Update 2025-07-25 08:50 OpenBSD/amd64-t14 2025-07-25 08:50:16 +02:00
c0dev0id
72850600e5 Update 2025-07-23 20:58 OpenBSD/amd64-t14 2025-07-23 20:58:48 +02:00
c0dev0id
0d3de71e2c Update 2025-07-23 20:52 OpenBSD/amd64-t14 2025-07-23 20:52:22 +02:00
c0dev0id
d318a58bb0 Update 2025-07-23 20:50 OpenBSD/amd64-t14 2025-07-23 20:51:00 +02:00
c0dev0id
299a3c8b51 Update 2025-07-23 20:50 OpenBSD/amd64-dalek 2025-07-23 20:50:45 +02:00
c0dev0id
6a3fe358f3 Update 2025-07-23 20:36 OpenBSD/amd64-t14 2025-07-23 20:36:22 +02:00
c0dev0id
a0d78823ae Update 2025-07-23 08:45 OpenBSD/amd64-t14 2025-07-23 08:45:16 +02:00
c0dev0id
8f37eceb9a Update 2025-07-23 08:44 OpenBSD/amd64-dalek 2025-07-23 08:44:35 +02:00
c0dev0id
0530d9228b Update 2025-07-21 11:40 OpenBSD/amd64-dalek 2025-07-21 11:40:45 +02:00
c0dev0id
15b0116633 Update 2025-07-21 11:31 OpenBSD/amd64-dalek 2025-07-21 11:31:44 +02:00
c0dev0id
6bbb12e7b3 Update 2025-07-19 07:49 OpenBSD/amd64-dalek 2025-07-19 07:49:02 +02:00
c0dev0id
1a2d91b0d7 Update 2025-07-19 07:40 OpenBSD/amd64-t14 2025-07-19 07:40:13 +02:00
c0dev0id
13bedaa7d3 Update 2025-07-16 09:55 OpenBSD/amd64-t14 2025-07-16 09:55:28 +02:00
c0dev0id
3b839841ac Update 2025-07-16 09:55 OpenBSD/amd64-t14 2025-07-16 09:55:17 +02:00
c0dev0id
9f365fe933 Update 2025-06-08 11:15 OpenBSD/amd64-t14 2025-06-08 11:15:49 +02:00
c0dev0id
62d5edaf29 Update 2025-05-29 09:47 OpenBSD/amd64-t14 2025-05-29 09:47:51 +02:00
c0dev0id
1371b1c8a2 Update 2025-05-25 14:13 OpenBSD/amd64-t14 2025-05-25 14:13:50 +02:00
c0dev0id
e900fc1f35 Update 2025-04-07 09:42 OpenBSD/amd64-t14 2025-04-07 09:42:02 +02:00
c0dev0id
ed8624ef01 Update 2025-03-12 08:17 OpenBSD/amd64-t14 2025-03-12 08:17:57 +01:00
c0dev0id
475bef8131 Update 2025-02-26 07:55 OpenBSD/amd64-t14 2025-02-26 07:55:21 +01:00
c0dev0id
3794862593 Update 2025-02-07 10:15 Linux/x86_64-ld5587 2025-02-07 10:15:31 +01:00
c0dev0id
8bce1b28b3 Update 2025-02-06 08:42 OpenBSD/amd64-t14 2025-02-06 08:42:16 +01:00
c0dev0id
7fc3348d20 Update 2025-02-02 11:02 OpenBSD/amd64-t14 2025-02-02 11:02:11 +01:00
c0dev0id
068de67638 Update 2025-02-01 18:41 OpenBSD/amd64-t14 2025-02-01 18:41:15 +01:00
c0dev0id
00f804c99f Update 2025-01-28 07:47 OpenBSD/amd64-t14 2025-01-28 07:47:21 +01:00
c0dev0id
ee9207d716 Update 2025-01-23 13:10 Darwin/arm64-GH2T6W9K6H 2025-01-23 13:10:13 +01:00
c0dev0id
3c6adda31b Update 2025-01-23 10:26 Darwin/arm64-GH2T6W9K6H 2025-01-23 10:26:26 +01:00
c0dev0id
7a70f07a67 Update 2025-01-18 09:07 OpenBSD/amd64-t14 2025-01-18 09:10:20 +01:00
c0dev0id
33471962fb Update 2025-01-14 14:03 Linux/x86_64-ld5587 2025-01-14 14:03:34 +01:00
c0dev0id
cc3afde694 Update 2025-01-08 08:15 OpenBSD/amd64-t14 2025-01-08 08:15:25 +01:00
c0dev0id
685a3b4c8d Update 2025-01-07 21:24 OpenBSD/amd64-t14 2025-01-07 21:24:53 +01:00
c0dev0id
b0cc6ce138 Update 2025-01-05 14:15 OpenBSD/amd64-t14 2025-01-05 14:15:46 +01:00
c0dev0id
a992796635 Update 2025-01-05 12:56 OpenBSD/amd64-t14 2025-01-05 12:56:30 +01:00
c0dev0id
20f3483f9c Update 2025-01-05 11:02 OpenBSD/amd64-t14 2025-01-05 11:02:20 +01:00
c0dev0id
87a300f0c4 Update 2025-01-05 10:36 OpenBSD/amd64-t14 2025-01-05 10:36:09 +01:00
c0dev0id
908090c41b Update 2025-01-05 09:22 OpenBSD/amd64-t14 2025-01-05 09:22:42 +01:00
c0dev0id
5f346e4848 Update 2025-01-03 14:45 OpenBSD/amd64-t14 2025-01-03 14:45:33 +01:00
c0dev0id
45969796dc Update 2025-01-03 14:41 OpenBSD/amd64-t14 2025-01-03 14:41:35 +01:00
c0dev0id
fa6a52b1a3 Update 2025-01-03 14:38 OpenBSD/amd64-t14 2025-01-03 14:38:07 +01:00
c0dev0id
02239e52a3 Update 2025-01-02 23:53 OpenBSD/amd64-t14 2025-01-02 23:53:34 +01:00
c0dev0id
767ba27c2b Update 2025-01-01 10:48 OpenBSD/amd64-t14 2025-01-01 10:48:50 +01:00
c0dev0id
08aaf050a6 Update 2025-01-01 10:06 OpenBSD/amd64-t14 2025-01-01 10:06:17 +01:00
c0dev0id
1c9a2b446a Update 2025-01-01 10:04 OpenBSD/amd64-t14 2025-01-01 10:04:08 +01:00
c0dev0id
6b2b5ae779 Update 2024-12-31 15:03 OpenBSD/amd64-t14 2024-12-31 15:03:55 +01:00
c0dev0id
d8fff6ec32 Update 2024-12-31 14:34 OpenBSD/amd64-t14 2024-12-31 14:34:23 +01:00
c0dev0id
26abaf99b2 Update 2024-12-31 13:15 OpenBSD/amd64-t14 2024-12-31 13:15:25 +01:00
c0dev0id
0bda01c32e Update 2024-12-31 13:12 OpenBSD/amd64-t14 2024-12-31 13:12:46 +01:00
c0dev0id
6db769365d Update 2024-12-31 12:24 OpenBSD/amd64-t14 2024-12-31 12:24:23 +01:00
c0dev0id
9f55042b33 Update 2024-12-31 10:47 OpenBSD/amd64-t14 2024-12-31 10:47:38 +01:00
c0dev0id
9ffce7022e Update 2024-12-26 20:41 OpenBSD/amd64-t14 2024-12-26 20:41:45 +01:00
c0dev0id
7c5d1f298f Update 2024-12-26 17:21 OpenBSD/amd64-t14 2024-12-26 17:21:55 +01:00
c0dev0id
3768436e21 Update 2024-12-26 15:09 OpenBSD/amd64-t14 2024-12-26 15:09:32 +01:00
c0dev0id
8d1878581b Update 2024-12-26 14:49 OpenBSD/amd64-t14 2024-12-26 14:49:00 +01:00
c0dev0id
e9581ec17d Update 2024-12-26 14:23 OpenBSD/amd64-t14 2024-12-26 14:23:38 +01:00
c0dev0id
7eb3f826fb Update 2024-12-25 21:13 OpenBSD/amd64-t14 2024-12-25 21:13:51 +01:00
c0dev0id
2357c34813 Update 2024-12-25 18:06 OpenBSD/amd64-t14 2024-12-25 18:06:24 +01:00
c0dev0id
1f15f715a6 Update 2024-12-25 15:43 OpenBSD/amd64-t14 2024-12-25 15:43:38 +01:00
c0dev0id
346463127c Update 2024-12-25 14:31 OpenBSD/amd64-t14 2024-12-25 14:31:11 +01:00
c0dev0id
3e58a36599 Update 2024-12-24 08:58 OpenBSD/amd64-t14 2024-12-24 08:58:49 +01:00
c0dev0id
6a240c970c Update 2024-12-23 22:17 OpenBSD/amd64-t14 2024-12-23 22:17:58 +01:00
c0dev0id
e548ab67c8 Update 2024-12-23 22:15 OpenBSD/amd64-t14 2024-12-23 22:15:16 +01:00
c0dev0id
b86b992a6a Update 2024-12-23 21:31 OpenBSD/amd64-t14 2024-12-23 21:31:59 +01:00
c0dev0id
31c62ae69a Update 2024-12-23 18:49 OpenBSD/amd64-t14 2024-12-23 18:49:14 +01:00
c0dev0id
ec7fbad49f Update 2024-12-23 18:34 OpenBSD/amd64-t14 2024-12-23 18:34:22 +01:00
c0dev0id
1bb57985ca Update 2024-12-23 18:21 OpenBSD/amd64-t14 2024-12-23 18:21:09 +01:00
c0dev0id
ac58f6baa9 Update 2024-12-23 17:32 OpenBSD/amd64-t14 2024-12-23 17:32:40 +01:00
c0dev0id
b2c7bcd12a Update 2024-12-23 16:38 OpenBSD/amd64-t14 2024-12-23 16:38:04 +01:00
c0dev0id
e2edc9d2b6 Update 2024-12-23 16:36 OpenBSD/amd64-t14 2024-12-23 16:36:55 +01:00
c0dev0id
70c63ad427 Update 2024-12-23 15:26 OpenBSD/amd64-t14 2024-12-23 15:26:32 +01:00
c0dev0id
ae5183fa58 Update 2024-12-23 14:32 OpenBSD/amd64-t14 2024-12-23 14:32:10 +01:00
c0dev0id
19fc60ef8b Update 2024-12-23 13:03 OpenBSD/amd64-t14 2024-12-23 13:03:14 +01:00
c0dev0id
0701e19f1e Update 2024-12-23 12:49 OpenBSD/amd64-t14 2024-12-23 12:49:42 +01:00
c0dev0id
1ecd621a69 Update 2024-12-23 12:39 OpenBSD/amd64-t14 2024-12-23 12:39:36 +01:00
c0dev0id
b3b69a682a Update 2024-12-23 11:45 OpenBSD/amd64-t14 2024-12-23 11:45:57 +01:00
c0dev0id
180588879c Update 2024-12-23 11:30 OpenBSD/amd64-t14 2024-12-23 11:30:16 +01:00
c0dev0id
0582999ac9 Update 2024-12-23 02:01 OpenBSD/amd64-t14 2024-12-23 02:01:54 +01:00
c0dev0id
fa50579054 Update 2024-12-23 00:29 OpenBSD/amd64-t14 2024-12-23 00:29:22 +01:00
c0dev0id
e27a96f17e Update 2024-12-22 22:44 OpenBSD/amd64-t14 2024-12-22 22:44:47 +01:00
c0dev0id
ebae25d46e Update 2024-12-22 21:08 OpenBSD/amd64-t14 2024-12-22 21:08:35 +01:00
c0dev0id
a145968b49 Update 2024-12-22 19:37 OpenBSD/amd64-t14 2024-12-22 19:37:24 +01:00
c0dev0id
7948d7cd1d Update 2024-12-22 19:14 OpenBSD/amd64-t14 2024-12-22 19:14:43 +01:00
c0dev0id
e304b53c34 Update 2024-12-22 17:20 OpenBSD/amd64-t14 2024-12-22 17:20:59 +01:00
c0dev0id
2e1234e383 Update 2024-12-22 16:36 OpenBSD/amd64-t14 2024-12-22 16:36:59 +01:00
c0dev0id
d0c4c84117 Update 2024-12-22 11:01 OpenBSD/amd64-t14 2024-12-22 11:09:14 +01:00
c0dev0id
4ec4facf23 Update 2024-12-22 09:05 OpenBSD/amd64-t14 2024-12-22 11:09:14 +01:00
1334 changed files with 202520 additions and 317048 deletions

View File

@@ -1,7 +1,6 @@
! -- CURSOR --! ! -- CURSOR --!
!Xcursor.size: 32 Xcursor.size: 48
Xcursor.size: 32 Xcursor.theme: Adwaita
Xcursor.theme:
xterm.cursorTheme: xterm.cursorTheme:
! -- XFT -- ! ! -- XFT -- !

View File

@@ -1,14 +0,0 @@
#!/bin/sh
ZONE=codevoid.de
if [ ! -z $1 ]
then
ZONE=$1
fi
ssh -t dns.codevoid.de \
"doas vim /var/nsd/zones/master/$ZONE \
&& doas nsd-control reload"
sleep 2

View File

@@ -1,20 +0,0 @@
#!/bin/sh
. $HOME/.bin/_config
print "Tarsnap Restore:"
if [ -z "$1" ]; then
doas tarsnap --list-archives | sort
printf "Usage: restore <key_id>\n"
exit 2
fi
_backup="$(doas tarsnap --list-archives | grep "$1")"
if [ -z "$_backup" ]; then
print "No backup with key id $1 found."
exit 1
fi
mkdir "restore_$1"
doas tarsnap --humanize-numbers -xvf "$_backup" -C "restore_$1"
print "Data restored in $(readlink -f "restore_$1")"

View File

@@ -69,7 +69,8 @@ needs() {
|| add="$add $x" || add="$add $x"
done done
[ ! -z "$add" ] \ [ ! -z "$add" ] \
&& doas pkg_add -- $add && doas pkg_add -- $add \
|| true
} }
# #

85
.bin/aria Executable file
View File

@@ -0,0 +1,85 @@
#!/bin/sh
DIR="/home/sdk/.aria2"
mkdir -p "$DIR"
SECOPTS="\
--bt-enable-lpd=false
--enable-peer-exchange=false
--enable-dht=false
--enable-dht6=false
"
PUBLIC="\
--dht-listen-port=55500
--bt-enable-lpd=true
--enable-peer-exchange=true
--enable-dht=true
--enable-dht6=true
"
DEFAULT="\
--auto-save-interval=60
--listen-port=55500
--disk-cache=256M
--bt-save-metadata=true
--bt-load-saved-metadata=true
--bt-prioritize-piece=head=10M,tail=10M
--content-disposition-default-utf8=true
--dht-file-path=$DIR/dht.dat
--dht-file-path6=$DIR/dht6.dat
--save-cookies=$DIR/cookies.dat
--save-session=$DIR/session.dat
"
for cmd in $@
do
case $cmd in
seed|upload|up)
OPTS="$OPTS
--seed-ratio=0.0
--max-overall-upload-limit=5M
--max-overall-download-limit=200K
--check-integrity=true
--bt-hash-check-seed=true
--bt-seed-unverified=true
-j 100
"
shift ;;
download|dl)
OPTS="$OPTS
--max-overall-upload-limit=200K
--max-overall-download-limit=85M
--seed-time=0
--lowest-speed-limit=30K
--bt-request-peer-speed-limit=100K
--file-allocation=trunc
-j 6
"
shift ;;
overwrite|force)
OPTS="$OPTS
--allow-overwrite=true
"
shift ;;
enc|encrypt) OPTS="$OPTS
--bt-require-crypto
--bt-min-crypto-level=arc4
"
shift ;;
pub|public) SECOPTS="$PUBLIC"
shift ;;
seq|1) OPTS="$OPTS
-j 1 -Z
"
shift ;;
esac
done
set -x
if [ -z "$@" ]
then
aria2c $DEFAULT $OPTS $SECOPTS *.torrent
else
aria2c $DEFAULT $OPTS $SECOPTS "$@"
fi

150
.bin/blog Executable file
View File

@@ -0,0 +1,150 @@
#!/bin/sh
# hugo cli frontend
# needs: sh, fzf, grep, cat, cut tr, date (bsd date...), hugo, vim
# deployments are handled using a Makefile (bring your own...)
cd "$HOME/blog"
for _arg
do
case $_arg in
update)
make update
exit 0
;;
esac
done
# extra options appended to the menu
_extra="---
maintenance * Maintenance Mode
new * New Post
quit * Quit Main Menu"
# main loop
while [ -z "$_quit" ]
do
# parse csv, build and show list
_selection=$(hugo list all \
| grep -Ev ^path \
| while read _line
do
# csv fields:
# 1: path
# 2: slug
# 3: title
# 4: date
# 5: expiryDate
# 6: publishDate
# 7: draft
# 8: permalink
# 9: kind
# 10: section
_file="$(echo $_line | cut -d"," -f1)"
_title="$(echo $_line | cut -d"," -f3)"
_draft=$(echo $_line | cut -d"," -f7)
_draft_fmt=$([ "$_draft" == "true" ] && echo "(draft)")
_date="$(echo $_line | cut -d"," -f4)"
_date_fmt=$(date -f "%Y-%m-%dT%H:%M:%S" -j "$_date" +"%Y-%m-%d %H:%M")
_type=$(echo "$_file" | grep -q "_index.md$" && echo "page" || echo "post")
echo "$_file * $_date_fmt | $_type | $_title $_draft_fmt"
done | (sort -t" " -k 2; echo "$_extra") \
| fzf -e --tac +s --with-nth 2.. \
| cut -d" " -f1)
### functions
_new() {
unset _newquit
while [ -z "$_newquit" ]
do
unset _newtitle
unset _filename
echo "Enter Post Title"
echo -n ": "
read _newtitle
if [ -n "$_newtitle" ]
then
# Welcome to my awful filename generator / sanitizer.
# Improvements are welcome!
_filename=$(echo "$_newtitle" \
| tr -d '?!%$:\\' \
| tr ' ./' '_' \
| tr -s '_' \
| tr '[:upper:]' '[:lower:]' \
| sed 's/_$//g;s/^_//g')
fi
if [ -n "$_filename" ]
then
echo "Creating:"
echo "File: content/posts/$_filename.md"
echo "Title: $_newtitle"
echo -n "Ok? [Y/n]: "
read _ok
case "$_ok" in
[nN]) ;;
*) hugo new content --editor=vim "content/posts/$_filename.md"
_newquit=1
;;
esac
else
echo "No title entered. Returning to menu."
_newquit=1
sleep 1
fi
done
}
_edit_entry() {
unset _quitmenu
while [ -z "$_quitmenu" ]
do
clear
_f="${_newname:-$1}"
echo "--- $_f:"
echo
head -15 "$_f"
echo "---"
echo
echo "Filename: $(basename "$_f")"
echo "Options: [E]dit, [D]elete, [R]ename, [T]oggle draft, [Q]uit Edit Menu"
echo -n ": "
read _opt
case $_opt in
[dD]) mkdir -p .trash; mv -f "$_f" .trash/
_quitmenu=1 ;;
[qQ]) return ;;
[tT]) grep -qE '^draft.*=.*false' "$_f" \
&& sed -i 's/^draft.*=.*false/draft = true/' "$_f" \
|| sed -i 's/^draft.*=.*true/draft = false/' "$_f" ;;
[rR]) echo "old: $(basename "$_f")"
echo -n "new: "
read _newname;
echo -n "ok? [Y/n]: "
read _ok
case "$_ok" in
[nN]) unset _newname ;;
*) _newname="content/posts/$_newname"
mv -vf "$_f" "$_newname"
;;
esac
;;
*) vim "$_f" ;;
[qQ]) _quitmenu=1 ;;
esac
done
}
case "$_selection" in
new) _new ;;
---) ;;
maintenance) make maintenance ;;
quit) _quit=1; echo "Good bye." ;;
*) [ -n "$_selection" ] \
&& _edit_entry "$_selection" \
|| _quit=1 ;;
esac
done

10
.bin/bupstash-backup Executable file
View File

@@ -0,0 +1,10 @@
#!/bin/sh
hostname=$(hostname)
year=$(date +%Y)
month=$(date +%m)
day=$(date +%d)
timestamp="$year-$month-$day $(date +"%H:%M")"
set -x
bupstash put --print-file-actions --print-stats hostname="$hostname" timestamp="$timestamp" year="$year" month="$month" day="$day" $@

101
.bin/cam
View File

@@ -1,4 +1,101 @@
#!/bin/sh #!/bin/sh
#ffplay -f v4l2 -list_formats all -i /dev/video0
_SWM_WS=-1 ffplay -loglevel quiet -f v4l2 -input_format mjpeg -video_size 424x240 -i /dev/video0 $@ &
# defaults
_format="-input_format mjpeg"
_dev="/dev/video0"
# loop through arguments
for arg in $@
do
# set values based of arguments found
case $arg in
s|start) _start=1 ;;
k|kill|stop) _stop=1 ;;
l|list) _list=1 ;;
30) _fps="-framerate 30" ;;
60) _fps="-framerate 60" ;;
raw) _format="-input_format yuyv422" ;;
nv12) _format="-input_format nv12" ;;
fullhd) _res="-video_size 1920x1080" ;;
hd) _res="-video_size 1280x720" ;;
sd) _res="-video_size 640x360" ;;
max) _res="max" ;;
[0-9]*x[0-9]*) _res="-video_size $arg" ;;
[0-9]) _dev="/dev/video$arg" ;;
*) _unknown="$_unknown $arg" ;;
esac
shift;
done
if [ ! -z "$_unknown" ]
then
echo "unknown parameter(s): $_unknown"
fi
# set resolution
if [ x"$_res" == x"max" ]
then
_res="-video_size $(ffplay -f v4l2 -list_formats all -i $_dev 2>&1 \
| grep mjpeg \
| xargs \
| cut -d":" -f4 \
| tr ' ' '\n' \
| sort -n \
| tail -1
)"
_format="-input_format mjpeg"
fi
# list supported formats + resolutions
if [ ! -z "$_list" ]
then
command="$(echo "ffplay -f v4l2 -list_formats all -i $_dev")"
echo "starting: $command"
$command 2>&1 \
| grep '^\[video4linux2' \
| cut -d: -f3,4 \
| sed -e 's/^[ \t]*//;s/ : /: /'
exit 0
fi
if [ ! -z "$_start" ]
then
command="ffplay -loglevel quiet -f v4l2 $_fps $_format $_res -i $_dev"
echo "starting: $command" | xargs
_SWM_WS=-1 $command > /dev/null 2>&1 &
[ $? -ne 0 ] \
&& echo "ffplay couldn't start"
exit 0
fi
if [ ! -z "$_stop" ]
then
echo "stopping: ffplay -loglevel quiet -f v4l2"
pkill -qf "ffplay -loglevel quiet -f v4l2"
exit 0
fi
if [ $(( _start + _stop + _list )) -eq 0 ]
then
echo "usage: cam command [framerate] [format] [resolution] [device]"
echo " commands:"
echo " start - start camera"
echo " stop - stop camera"
echo " list - list supported formats and resolutions"
echo " formats:"
echo " raw - reads the yuyv422 stream (instead of mjpeg)"
echo " nv12 - reads the nv12 stream (instead of mjpeg)"
echo " resolutions:"
echo " sd - set video size to 640x360"
echo " hd - set video size to 1280x720"
echo " fullhd - set video size to 1920x1080"
echo " max - set maximum video size (implies mjpeg format)"
echo " <width>x<height> - manually set resolution (see list command)"
echo " framerates:"
echo " 30 - set framerate to 30 fps"
echo " 60 - set framerate to 60 fps"
echo " <device> - set video device number (defaults to 0)"
echo
echo " Note: ffplay may not start or fall back to internal defaults when options (or combinations thereof) are not supported by the camera."
exit 2
fi

11
.bin/cdrip2flac Executable file
View File

@@ -0,0 +1,11 @@
#!/bin/sh
set -xe
alias flac_encode="flac -e --best --delete-input-file"
doas chown sdk /dev/rcd0* /dev/cd0*
cdio cdrip
for i in *.wav;
do
flac_encode "$i" -o "${i%%.wav}.flac";
done
picard *.flac
cdio eject

View File

@@ -1,62 +1,146 @@
#!/bin/sh #!/bin/sh
#/usr/local/bin/ungoogled-chromium \
#export DBUS_SESSION_BUS_ADDRESS="unix:path=/dev/null"
export ENABLE_WASM=Yes
/usr/local/bin/chrome \
--no-first-run \
--disable-crash-reporter \
--disable-logging \
--disable-login-animations \
--disable-notifications \
--disable-infobars \
--disable-dev-shm-usage \
--log-level=0 \
--hide-crash-restore-bubble \
--no-default-browser-check \
--high-dpi-support=1 \
--force-device-scale-factor=1.5 \
--new-window "$@"
# --bwsi \ # flag documentation:
# --disable-auto-reload \ # https://peter.sh/experiments/chromium-command-line-switches/
# --disable-breakpad \
# --disable-client-side-phishing-detection \ # helper functions
# --disable-component-cloud-policy \ addflag() { FLAGS="$FLAGS $1"; }
# --disable-component-update \ enable() { ENABLED_FEATURES="$ENABLED_FEATURES $1"; }
# --disable-crash-reporter \ disable() { DISABLED_FEATURES="$DISABLED_FEATURES $1"; }
# --disable-device-discovery-notifications \
# --disable-logging \ ###
# --disable-login-animations \ ### SETUP ENVIRONMENT
# --disable-notifications \ ###
# --disable-pinch \
# --disable-software-rasterizer \ # disable WASM (OpenBSD specific)
# --disable-chrome-browser-cloud-management \ #export ENABLE_WASM=0
# --disable-field-trial-config \
# --disable-cookie-encryption \ # Nuke DBUS
# --disable-cloud-print-proxy \ # some webpages suggest value "disabled:"
# --dbus-stub \ export DBUS_SESSION_BUS_ADDRESS="unix:path=/dev/null"
# --cros-disks-fake \
# --disable-stack-profiler \ ###
# --disable-touch-drag-drop \ ### CHROMIUM FLAGS
# --disable-usb-keyboard-detect \ ###
# --disable-default-apps \
# --disable-histogram-customizer \ # disable pledge (OpenBSD specific)
# --disable-in-process-stack-traces \ #addflag "--no-sandbox"
# --no-service-autorun \
# --no-experiments \ # disable unveil (OpenBSD specific)
# --use-gl=egl \ #addflag "--disable-unveil"
# --force-dark-mode \
# --enable-features=WebUIDarkMode \ # Skip First Run tasks as well as not showing additional dialogs,
# --hide-crash-restore-bubble \ # prompts or bubbles. Suppressing dialogs, prompts, and bubbles is
# --no-default-browser-check \ # important as this switch is used by automation (including performance
# --no-proxy-server \ # benchmarks) where it's important only a browser window is shown. This
# --no-recovery-component \ # may not actually be the first run or the What's New page. Overridden
# --password-store=basic \ # by kForceFirstRun (for FRE) and kForceWhatsNew (for What's New). This
# --structured-metrics-disabled \ # does not drop the First Run sentinel and thus doesn't prevent first run
# --wm-window-animations-disabled \ # from occurring the next time chrome is launched without this flag. It
# #--enable-features=RunVideoCaptureServiceInBrowserProcess,WebUIDarkMode \ # also does not update the last What's New milestone, so does not prevent
# #--use-gl=egl \ # What's New from occurring the next time chrome is launched without this
# --disable-yuv-image-decoding \ # flag.
# --use-gl=desktop \ addflag "--no-first-run"
# --high-dpi-support=1 \
# --force-device-scale-factor=1.5 \ # Enables TLS/SSL errors on localhost to be ignored (no interstitial, no
# blocking of requests).
addflag "--allow-insecure-localhost"
# If present animations are disabled
addflag "--wm-window-animations-disabled"
# Select which implementation of GL the GPU process should use.
# Options are:
# desktop: whatever desktop OpenGL the user has installed (Linux and Mac default).
# egl: whatever EGL / GLES2 the user has installed (Windows default - actually ANGLE).
# swiftshader: The SwiftShader software renderer.
addflag "--use-gl=desktop"
# Disable structured metrics logging of cros actions.
addflag "--structured-metrics-disabled"
# Enables cros disks fake behavior. If the switch is set, fake cros disk
# D-Bus client is initialized and USB events do not reach chrome.
addflag "--cros-disks-fake"
# Specifies which encryption storage backend to use. Possible values are
# kwallet, kwallet5, kwallet6, gnome-libsecret, basic. Any other value
# will lead to Chrome detecting the best backend automatically.
addflag "--password-store=basic"
# Disables the service process from adding itself as an autorun process.
# This does not delete existing autorun registrations, it just prevents
# the service from registering a new one.
addflag "--no-service-autorun"
# Prevent downloading and running the recovery component.
addflag "--no-recovery-component"
addflag "--no-proxy-server"
addflag "--no-experiments"
addflag "--no-default-browser-check"
addflag "--log-level=0"
addflag "--high-dpi-support=1"
addflag "--hide-crash-restore-bubble"
addflag "--force-device-scale-factor=1.5"
addflag "--force-dark-mode"
addflag "--enable-gpu-rasterization"
addflag "--enable-zero-copy"
# addflag "--enable-unsafe-webgpu" # leads to banner "stability and security will suffer
addflag "--ignore-gpu-blocklist"
# fix webcam issues?
# addflag "--disable-yuv-image-decoding"
#
addflag "--disable-usb-keyboard-detect"
addflag "--disable-touch-drag-drop"
addflag "--disable-stack-profiler"
#addflag "--disable-software-rasterizer"
addflag "--disable-pinch"
addflag "--disable-notifications"
addflag "--disable-login-animations"
addflag "--disable-logging"
addflag "--disable-infobars"
addflag "--disable-in-process-stack-traces"
addflag "--disable-histogram-customizer"
addflag "--disable-field-trial-config"
addflag "--disable-device-discovery-notifications"
# addflag "--disable-dev-shm-usage"
addflag "--disable-default-apps"
# Disable crash reporting
addflag "--disable-crash-reporter"
addflag "--disable-cookie-encryption"
addflag "--disable-component-update"
addflag "--disable-component-cloud-policy"
addflag "--disable-cloud-print-proxy"
addflag "--disable-client-side-phishing-detection"
addflag "--disable-chrome-browser-cloud-management"
addflag "--disable-breakpad"
addflag "--disable-auto-reload"
# addflag "--dbus-stub" # default on non chrome-os
addflag "--bwsi" # force guest mode (no sign-in)
###
### ENABLE / DISABLE PROCESS FEATURES
###
enable "WebUIDarkMode" # enables dark mode
# enable RunVideoCaptureServiceInBrowserProcess # fixes webcam issues by avoiding multiple /dev/video opens
enable "VaapiVideoDecoder"
enable "VaapiVideoEncoder"
disable "IndexedDBCompressValuesWithSnappy" # disable indexdb compression, speeds up facebook
disable "Vulkan"
disable "UseChromeOSDirectVideoDecoder"
enable "VaapiVideoDecodeLinuxGL"
enable "VaapiIgnoreDriverChecks"
disable "UseSkiaRenderer"
# add features to flag list
addflag "--enable-features=$(echo "$ENABLED_FEATURES" | tr -s " " | sed 's/^ //g' | tr ' ' ',')"
addflag "--enable-features=$(echo "$DISABLED_FEATURES" | tr -s " " | sed 's/^ //g' | tr ' ' ',')"
# finally start chrome...
set -x
/usr/local/bin/chrome $FLAGS --new-window "$@"

12
.bin/create-torrent Executable file
View File

@@ -0,0 +1,12 @@
#!/bin/sh
# source https://github.com/aria2/aria2/issues/663
export PATH=$HOME/.cargo/bin:$PATH
[ ! -f $HOME/.cargo/bin/imdl ] \
&& cargo install -f imdl
set -x
imdl torrent create --input "$1"
imdl torrent show --input "$1.torrent"
imdl torrent verify --input "$1.torrent" --content "$1"
imdl torrent link --input "$1.torrent"

6
.bin/cvs-update Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/sh -ex
CVSROOT="sdk@cvs.openbsd.org:/cvs"
export CVSROOT
doas -u sdk cvs -d $CVSROOT -z1 -q up -Pd -A $@

View File

@@ -21,7 +21,7 @@ touch "${HISTFILE}"
read_input() { read_input() {
local S=$( { echo "paste_from_clipboard"; tail -r ${HISTFILE}; } \ local S=$( { echo "paste_from_clipboard"; tail -r ${HISTFILE}; } \
| awk '!seen[$0]++' \ | awk '!seen[$0]++' \
| ${DMENU_CMD} -p "Bookmarks" -l 20) | ${DMENU_CMD} -p "Bookmarks")
case "${S}" in case "${S}" in
paste_from_clipboard) S=$(xclip -o | head -n 1); ;; paste_from_clipboard) S=$(xclip -o | head -n 1); ;;
@@ -91,7 +91,7 @@ Zalando"
esac esac
local S="$(printf "%s\n%s" "${DEFAULT}" "${SE}" \ local S="$(printf "%s\n%s" "${DEFAULT}" "${SE}" \
| ${DMENU_CMD} -p "Search Where?" -l 20)" | ${DMENU_CMD} -p "Search Where?")"
C=$(echo "$C" | sed 's/ /%20/g') C=$(echo "$C" | sed 's/ /%20/g')
case "${S}" in case "${S}" in
OPEN*) URI="${C}"; ;; OPEN*) URI="${C}"; ;;
@@ -136,7 +136,12 @@ choose_browser() {
gopher://*) DEFAULT="Lagrange (default)"; ;; gopher://*) DEFAULT="Lagrange (default)"; ;;
gemini://*) DEFAULT="Lagrange (default)"; ;; gemini://*) DEFAULT="Lagrange (default)"; ;;
*console.hetzner.cloud*) DEFAULT="Firefox (default)"; ;; *console.hetzner.cloud*) DEFAULT="Firefox (default)"; ;;
*youtube.com/watch*) DEFAULT="Mpv (default)"; ;; *amazon.com*) DEFAULT="Chrome (default)"; ;;
*club.de*) DEFAULT="Chrome (default)"; ;;
*life.com*) DEFAULT="Chrome (default)"; ;;
*videos.com*) DEFAULT="Chrome (default)"; ;;
*comdirect.de*) DEFAULT="Chrome (default)"; ;;
*youtube.com*) DEFAULT="Chrome (default)"; ;;
*media.ccc.de/v/*) DEFAULT="Mpv (default)"; ;; *media.ccc.de/v/*) DEFAULT="Mpv (default)"; ;;
*.pdf|*.cb|*.ps) DEFAULT="Zathura (default)"; ;; *.pdf|*.cb|*.ps) DEFAULT="Zathura (default)"; ;;
*.mp4|*.m4v|*.mkv) DEFAULT="Mpv (default)"; ;; *.mp4|*.m4v|*.mkv) DEFAULT="Mpv (default)"; ;;
@@ -151,7 +156,7 @@ choose_browser() {
[Qq]uteb*r*) BROWSER="qutebrowser -R" ;; [Qq]uteb*r*) BROWSER="qutebrowser -R" ;;
[Ss]urf*) BROWSER=surf ;; [Ss]urf*) BROWSER=surf ;;
[Oo]tter*r*) BROWSER=otter-browser ;; [Oo]tter*r*) BROWSER=otter-browser ;;
[Ll]uakit*) BROWSER="luakit -Un" ;; [Ll]uakit*) BROWSER="luakit -v -U" ;;
[Cc]hrome*) BROWSER=chrome ;; [Cc]hrome*) BROWSER=chrome ;;
[Ff]irefox*) BROWSER=firefox ;; [Ff]irefox*) BROWSER=firefox ;;
[Tt]or-B*r*) BROWSER=tor-browser ;; [Tt]or-B*r*) BROWSER=tor-browser ;;
@@ -170,6 +175,6 @@ save_history() {
# main program starts here. # main program starts here.
read_input read_input
choose_wrapper choose_wrapper
# choose_browser #choose_browser
save_history save_history
$BROWSER "$(printf '%s' "${URI}" | sed 's/ /%20/g')" & $BROWSER "$(printf '%s' "${URI}" | sed 's/ /%20/g')" > /home/sdk/browser.log 2>&1 &

11
.bin/dexec_man Executable file
View File

@@ -0,0 +1,11 @@
#!/bin/sh
. $HOME/.bin/_config
SEL=$(man -k any= | $DMENU_CMD -l 10 -p "Man")
[ -z "$SEL" ] && exit 0
N=$(echo "$SEL" | cut -d"(" -f2 | cut -d")" -f1)
M=$(echo "$SEL" | cut -d"(" -f1 | cut -d"," -f1)
sterm -e man -s $N $M

78
.bin/fb-getip.sh Executable file
View File

@@ -0,0 +1,78 @@
#!/bin/sh
# needs: curl, yq (xq)
# usage: fb-getip.sh [ip address]
#
# Endpoints & Services:
# http://fritz.box:49000/tr64desc.xml
# AVM TR064 Documentation:
# https://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/AVM_TR-064_first_steps.pdf
# https://www.broadband-forum.org/technical/download/TR-064.pdf
FBHOST="fritz.box"
[ ! -z "$1" ] && FBHOST="$1"
# Variable parts, which can be looked up in the TR-064 documentation
SERVICE=WANIPConnection
ACTION=GetExternalIPAddress
# Endpoints supported by the fritzbox, can be looked up at the
# "Endpoint & Services" URL.
ENDPOINT=WANIPConn1
# SOAP protocol payload (https://en.wikipedia.org/wiki/SOAP)
# This is the language the fritzbox is "speaking". So we create this
# payload with the appropriage Service, Action variables.
PAYLOAD=\
'<?xml version="1.0" encoding="utf-8" ?>
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:'$ACTION' xmlns:u="urn:schemas-upnp-org:service:'$SERVICE':1" />
</s:Body>
</s:Envelope>'
# We use curl to send the payload with the appropriate soap+upnp header
# to the fritzbox and receive the SOAP response.
#
# Header explanation:
#
# - Header: Content-Type - describes that we send format text/xml with utf8 encoding.
# See HTTP Specification:
# https://www.rfc-editor.org/rfc/rfc9110.html#name-content-type
# (Chapter 8.3)
#
# - Header: SoapAction... - it's redundant with the payload information.
# See SoapAction specification:
# https://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383528
# (Chapter 6.1.1)
#
# - SoapAction:<parameter>... - This <parameter> is "urn:schemas-upnp-org:<service>
# Each <service> has it's own specifcation.
# WANIPConnection Service Specification:
# https://upnp.org/specs/gw/UPnP-gw-WANIPConnection-v1-Service.pdf
# (Chapter 2.1)
RESPONSE="$(curl -s "http://$FBHOST:49000/igdupnp/control/$ENDPOINT" \
-H "Content-Type: text/xml; charset=utf-8" \
-H "SoapAction:urn:schemas-upnp-org:service:$SERVICE:1#$ACTION" \
-d "$PAYLOAD")"
# The SOAP response is ugly XML (just like the requst), so we use "xq",
# which converts XML to JSON and allows us to operate on it with "jq"
# syntax.
# yq/xq documentation: https://kislyuk.github.io/yq
# jq documentation: https://jqlang.github.io/jq/manual
# Tutorial: https://www.ashbyhq.com/blog/engineering/jq-and-yq
#
# (once understood, these tools are _very_ powerful! - worth to learn)
# This "case" is only there so we can do a different kind parsing for
# other endpoints. Like when the ACTION variable is changed the parsing
# needs to be adapted.
case "$ACTION" in
GetExternalIPAddress) printf '%s' "$RESPONSE" \
| xq -r '."s:Envelope"."s:Body"."u:GetExternalIPAddressResponse".NewExternalIPAddress'
;;
*) printf '%s' "$RESPONSE"
;;
esac

View File

@@ -1,5 +1,9 @@
#!/bin/sh #!/bin/sh
export XDG_CACHE_HOME=/tmp firefox export XDG_CACHE_HOME=/tmp
export MOZ_X11_EGL=1 export MOZ_X11_EGL=1
export MOZ_PLUGIN_PATH=/usr/local/lib/mozilla/plugins
unset _SWM_WS
/usr/local/bin/firefox "$@" pgrep -qf bin/firefox && args="--new-window"
/usr/local/bin/firefox $args "$@"

29
.bin/format-exfat.sh Executable file
View File

@@ -0,0 +1,29 @@
#!/bin/sh -e
_dev="$1"
[ -z $_dev ] && printf "usage: %s <sd2>\n" "$(basename $0)" && exit 2
[ $(id -u) -gt 0 ] && printf "you need superuser rights\n" && exit 2
dmesg | grep "$_dev" | grep -A1 scsibus | tail -n 2
printf "Format ${_dev} [y/N]? "
read
case $REPLY in
[yY]) ;;
*) exit 0; ;;
esac
printf "Overwriting first MBs with zeros:"
dd of=/dev/r${_dev}c if=/dev/zero bs=1M count=1 > /dev/null 2>&1
printf " ✅\n"
printf "Creating exFAT / NTFS partition:"
echo "edit 0\n07\n\n2048\n*\nw\nq\n" | fdisk -e "$_dev" > /dev/null 2>&1
printf " ✅\n"
printf "Creating exFAT file system (this may take a while)...\n"
mkexfatfs -s 2048 "/dev/${_dev}i"
printf "Creating exFAT file system: ✅\n"
printf "Mount:\ndoas mount.exfat /dev/%si /mnt\n" "$_dev"

View File

@@ -19,11 +19,11 @@ dd of=/dev/r${_dev}c if=/dev/zero bs=1M count=1 > /dev/null 2>&1
printf " ✅\n" printf " ✅\n"
printf "Creating FAT32 partition:" printf "Creating FAT32 partition:"
echo "edit 0\n0B\n\n512\n*\nw\nq\n" | fdisk -e "$_dev" > /dev/null 2>&1 echo "edit 0\n0B\n\n1024\n*\nw\nq\n" | fdisk -e "$_dev" > /dev/null 2>&1
printf " ✅\n" printf " ✅\n"
printf "Creating FAT32 file system (this may take a while)...\n" printf "Creating FAT32 file system (this may take a while)...\n"
newfs_msdos -F32 -b65536 "${_dev}i" newfs_msdos -F32 -b65536 "${_dev}i"
printf "Creating FAT32 file system: ✅\n" printf "Creating FAT32 file system: ✅\n"
printf "Mount:\ndoas mkdir -p /mnt/%s && doas mount_msdos /dev/%si /mnt/%s\n" "$_dev" "$_dev" "$_dev" printf "Mount:\ndoas mount_msdos /dev/%si /mnt\n" "$_dev"

81
.bin/g Executable file
View File

@@ -0,0 +1,81 @@
#!/bin/sh
# check if there's .git dir in a parent dir
isgit() {
_path="$PWD"
while [ -n "$_path" ]
do
if [ -d "$_path/.git" ]
then
return 0
fi
_path="${_path%/*}"
done
return 1
}
if ! isgit
then echo "no git repository"
return
fi
_width=$(tput cols)
if [ -z "$_width" ]
then
_width=60
fi
[ $_width -lt 43 ] \
&& _width=43 \
|| _width=$(( _width - 3 ))
_origin=$(git remote get-url origin \
2> /dev/null)
[ -n "$_origin" ] \
&& echo "# origin: $_origin"
_upstream=$(git remote get-url upstream \
2> /dev/null)
[ -n "$_upstream" ] \
&& echo "# upstream: $_upstream"
_base=$(git --no-pager log \
--abbrev-commit \
--pretty=format:'%h | %an: %s' \
HEAD~2...origin/HEAD~1 \
2> /dev/null)
_branch=$(git --no-pager branch \
--no-color \
--show-current \
2> /dev/null)
[ -n "$_base" ] \
&& printf '%s\n' "# branch ($_branch) fork point: $_base" \
| sed "s/\(.\{$_width\}\).*/\1.../"
_log=$(git --no-pager log \
--reverse \
--abbrev-commit \
--date=format:'%d.%m.%y %H:%S' \
--pretty=format:'%h|%ad|%an: %s' \
...origin/HEAD \
2>/dev/null)
if [ -n "$_log" ]
then
echo "# local commits"
printf '%s\n' "$_log" | sed "s/\(.\{$_width\}\).*/\1.../"
else
echo "# no local commits"
fi
_stat=$(git --no-pager status \
--short 2>/dev/null)
if [ -n "$_stat" ]
then
echo "# local changes:"
echo "$_stat"
else
echo "# no local changes"
fi

23
.bin/got-notes Executable file
View File

@@ -0,0 +1,23 @@
#!/bin/cat
init: got init luakit.git
download: got clone git@github.com:luakit/luakit luakit.git
checkout: got checkout luakit.git luakit
commit: got commit
diff changes: got diff
diff branch main with patch: got diff main patch
list branches: got branch -l
switch/create branch: got branch testbranch
interactive revert: got revert -p -R .
rebase current branch on top of master: got update -b master
add file: got add
repo info: got info
import from CVS:
got import -r /var/git/src.git -I CVS -I obj /tmp/src

View File

@@ -1,296 +0,0 @@
#!/usr/bin/perl -w
my $debug = 0;
#
# ical2rem.pl -
# Reads iCal files and outputs remind-compatible files. Tested ONLY with
# calendar files created by Mozilla Calendar/Sunbird. Use at your own risk.
# Copyright (c) 2005, 2007, Justin B. Alcorn
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
#
# version 0.5.2 2007-03-23
# - BUG: leadtime for recurring events had a max of 4 instead of DEFAULT_LEAD_TIME
# - remove project-lead-time, since Category was a non-standard attribute
# - NOTE: There is a bug in iCal::Parser v1.14 that causes multiple calendars to
# fail if a calendar with recurring events is followed by a calendar with no
# recurring events. This has been reported to the iCal::Parser author.
# version 0.5.1 2007-03-21
# - BUG: Handle multiple calendars on STDIN
# - add --heading option for priority on section headers
# version 0.5 2007-03-21
# - Add more help options
# - --project-lead-time option
# - Supress printing of heading if there are no todos to print
# version 0.4
# - Version 0.4 changes all written or inspired by, and thanks to Mark Stosberg
# - Change to GetOptions
# - Change to pipe
# - Add --label, --help options
# - Add Help Text
# - Change to subroutines
# - Efficiency and Cleanup
# version 0.3
# - Convert to GPL (Thanks to Mark Stosberg)
# - Add usage
# version 0.2
# - add command line switches
# - add debug code
# - add SCHED _sfun keyword
# - fix typos
# version 0.1 - ALPHA CODE.
=head1 SYNOPSIS
cat /path/to/file*.ics | ical2rem.pl > ~/.ical2rem
All options have reasonable defaults:
--label Calendar name (Default: Calendar)
--lead-time Advance days to start reminders (Default: 3)
--todos, --no-todos Process Todos? (Default: Yes)
--heading Define a priority for static entries
--help Usage
--man Complete man page
Expects an ICAL stream on STDIN. Converts it to the format
used by the C<remind> script and prints it to STDOUT.
=head2 --label
ical2rem.pl --label "Bob's Calendar"
The syntax generated includes a label for the calendar parsed.
By default this is "Calendar". You can customize this with
the "--label" option.
=head2 --lead-time
ical2rem.pl --lead-time 3
How may days in advance to start getting reminders about the events. Defaults to 3.
=head2 --no-todos
ical2rem.pl --no-todos
If you don't care about the ToDos the calendar, this will surpress
printing of the ToDo heading, as well as skipping ToDo processing.
=head2 --heading
ical2rem.pl --heading "PRIORITY 9999"
Set an option on static messages output. Using priorities can made the static messages look different from
the calendar entries. See the file defs.rem from the remind distribution for more information.
=cut
use strict;
use iCal::Parser;
use DateTime;
use Getopt::Long 2.24 qw':config auto_help';
use Pod::Usage;
use Data::Dumper;
use vars '$VERSION';
$VERSION = "0.5.2";
# Declare how many days in advance to remind
my $DEFAULT_LEAD_TIME = 3;
my $PROCESS_TODOS = 1;
my $HEADING = "";
my $help;
my $man;
my $label = 'Calendar';
GetOptions (
"label=s" => \$label,
"lead-time=i" => \$DEFAULT_LEAD_TIME,
"todos!" => \$PROCESS_TODOS,
"heading=s" => \$HEADING,
"help|?" => \$help,
"man" => \$man
);
pod2usage(1) if $help;
pod2usage(-verbose => 2) if $man;
my $month = ['None','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
my @calendars;
my $in;
while (<>) {
$in .= $_;
if (/END:VCALENDAR/) {
push(@calendars,$in);
$in = "";
}
}
print STDERR "Read all calendars\n" if $debug;
my $startdate = DateTime->new( year => 2010,
month => 4,
day => 1,
time_zone => 'US/Eastern',
);
my $oneyear = DateTime::Duration->new( years => 1);
my $oneweek = DateTime::Duration->new( weeks => -1);
$startdate = DateTime->now + $oneweek;
my $enddate = DateTime->now + $oneyear;
print STDERR "About to parse calendars\n" if $debug;
my $parser = iCal::Parser->new('start' => $startdate,
'debug' => 0,
'end' => $enddate);
my $hash = $parser->parse_strings(@calendars);
print STDERR "Calendars parsed\n" if $debug;
##############################################################
#
# Subroutines
#
#############################################################
#
# _process_todos()
# expects 'todos' hashref from iCal::Parser is input
# returns String to output
sub _process_todos {
my $todos = shift;
my ($todo, @newtodos, $leadtime);
my $output = "";
$output .= 'REM '.$HEADING.' MSG '.$label.' ToDos:%"%"%'."\n";
# For sorting, make sure everything's got something
# To sort on.
my $now = DateTime->now;
for $todo (@{$todos}) {
# remove completed items
if ($todo->{'STATUS'} && $todo->{'STATUS'} eq 'COMPLETED') {
next;
} elsif ($todo->{'DUE'}) {
# All we need is a due date, everything else is sugar
$todo->{'SORT'} = $todo->{'DUE'}->clone;
} elsif ($todo->{'DTSTART'}) {
# for sorting, sort on start date if there's no due date
$todo->{'SORT'} = $todo->{'DTSTART'}->clone;
} else {
# if there's no due or start date, just make it now.
$todo->{'SORT'} = $now;
}
push(@newtodos,$todo);
}
if (! (scalar @newtodos)) {
return "";
}
# Now sort on the new Due dates and print them out.
for $todo (sort { DateTime->compare($a->{'SORT'}, $b->{'SORT'}) } @newtodos) {
my $due = $todo->{'SORT'}->clone();
my $priority = "";
if (defined($todo->{'PRIORITY'})) {
if ($todo->{'PRIORITY'} == 1) {
$priority = "PRIORITY 1000";
} elsif ($todo->{'PRIORITY'} == 3) {
$priority = "PRIORITY 7500";
}
}
if (defined($todo->{'DTSTART'}) && defined($todo->{'DUE'})) {
# Lead time is duration of task + lead time
my $diff = ($todo->{'DUE'}->delta_days($todo->{'DTSTART'})->days())+$DEFAULT_LEAD_TIME;
$leadtime = "+".$diff;
} else {
$leadtime = "+".$DEFAULT_LEAD_TIME;
}
$output .= "REM ".$due->month_abbr." ".$due->day." ".$due->year." $leadtime $priority MSG \%a $todo->{'SUMMARY'}\%\"\%\"\%\n";
}
$output .= 'REM '.$HEADING.' MSG %"%"%'."\n";
return $output;
}
#######################################################################
#
# Main Program
#
######################################################################
print _process_todos($hash->{'todos'}) if $PROCESS_TODOS;
my ($leadtime, $yearkey, $monkey, $daykey,$uid,%eventsbyuid);
print 'REM '.$HEADING.' MSG '.$label.' Events:%"%"%'."\n";
my $events = $hash->{'events'};
foreach $yearkey (sort keys %{$events} ) {
my $yearevents = $events->{$yearkey};
foreach $monkey (sort {$a <=> $b} keys %{$yearevents}){
my $monevents = $yearevents->{$monkey};
foreach $daykey (sort {$a <=> $b} keys %{$monevents} ) {
my $dayevents = $monevents->{$daykey};
foreach $uid (sort {
DateTime->compare($dayevents->{$a}->{'DTSTART'}, $dayevents->{$b}->{'DTSTART'})
} keys %{$dayevents}) {
my $event = $dayevents->{$uid};
if ($eventsbyuid{$uid}) {
my $curreventday = $event->{'DTSTART'}->clone;
$curreventday->truncate( to => 'day' );
$eventsbyuid{$uid}{$curreventday->epoch()} =1;
for (my $i = 0;$i < $DEFAULT_LEAD_TIME && !defined($event->{'LEADTIME'});$i++) {
if ($eventsbyuid{$uid}{$curreventday->subtract( days => $i+1 )->epoch() }) {
$event->{'LEADTIME'} = $i;
}
}
} else {
$eventsbyuid{$uid} = $event;
my $curreventday = $event->{'DTSTART'}->clone;
$curreventday->truncate( to => 'day' );
$eventsbyuid{$uid}{$curreventday->epoch()} =1;
}
}
}
}
}
foreach $yearkey (sort keys %{$events} ) {
my $yearevents = $events->{$yearkey};
foreach $monkey (sort {$a <=> $b} keys %{$yearevents}){
my $monevents = $yearevents->{$monkey};
foreach $daykey (sort {$a <=> $b} keys %{$monevents} ) {
my $dayevents = $monevents->{$daykey};
foreach $uid (sort {
DateTime->compare($dayevents->{$a}->{'DTSTART'}, $dayevents->{$b}->{'DTSTART'})
} keys %{$dayevents}) {
my $event = $dayevents->{$uid};
if (exists($event->{'LEADTIME'})) {
$leadtime = "+".$event->{'LEADTIME'};
} else {
$leadtime = "+".$DEFAULT_LEAD_TIME;
}
my $start = $event->{'DTSTART'};
print "REM ".$start->month_abbr." ".$start->day." ".$start->year." $leadtime ";
if ($start->hour > 0) {
print " AT ";
print $start->strftime("%H:%M");
# print " SCHED _sfun MSG %a %2 ";
# fix 2024-10-04
print " +15 MSG %a %2 ";
} else {
print " MSG %a ";
}
print "%\"$event->{'SUMMARY'}";
print " at $event->{'LOCATION'}" if $event->{'LOCATION'};
print "\%\"%\n";
}
}
}
}
exit 0;
#:vim set ft=perl ts=4 sts=4 expandtab :

View File

@@ -1,3 +1,3 @@
#!/bin/sh #!/bin/sh
ipmitool -U ADMIN -P $(pass Local/TweetyIPMI | head -1) \ ipmitool -U ADMIN -P $(pass Local/TweetyIPMI | head -1) \
-I lanplus -H 10.20.30.21 $@; -I lanplus -H tweety-ipmi.home.codevoid.de $@;

108
.bin/lddcopy Executable file
View File

@@ -0,0 +1,108 @@
#!/bin/sh
# FIXME: does not work with space in filenames or directories
# (can be fixed by | while read ... the ldd output, but.. why?)
# FIXME: directory permissions are not copied
# (can be fixed with stat -f '%p %u %g' . and walk the path with mkdir -m ...)
##
## USAGE
##
_usage() {
echo "usage: mkchroot [-xn] [-u or executable] directory"
echo "options: -u - runs for all executables found in /bin/ directories"
echo " -x - copy stuff required to connect to X"
echo " -n - copy stuff required for networking"
}
##
## HANDLE ARGUMENTS
##
while getopts xnuh arg
do
case $arg in
x) _with_x=1 ;; # creates /tmp with X connection
n) _with_network=1 ;; # copies resolv.conf
u) _update_mode=1 ;; # updates the existing directory
h) _usage; exit 0 ;;
esac
done
shift $(($OPTIND - 1))
if [ -z "$1" ] && [ -z "$_update_mode" ]
then
_usage
exit 1
fi
if [ -z "$2" ] && [ -z "$_update_mode" ]
then
_usage
exit 1
fi
if [ "$_update_mode" == "1" ]
then
_indir="$1"
else
_infile="$1"
_indir="$2"
fi
###
### FUNCTIONS
###
_ldd_extract() {
for _file in $(ldd "$1" | awk '/\// { print $7 }' | xargs)
do
_name="$(basename "$_file")"
_dir="$2/$(dirname "$_file" | cut -b2-)"
if [ ! -d "$_dir" ]
then
echo "mkdir: $_dir"
mkdir -p "$_dir"
fi
if [ ! -f "$_dir/$_name" ]
then
echo "copy: $_file -> $_dir/$_name"
cp -af "$_file" "$_dir/$_name"
else
echo "skip: $_file -> $_dir/$_name (existing)"
fi
done
}
_find_binfile() {
# remove basedir
_f=$(echo "$1" | sed "s|${1%%/*}||g")
_ofile="$(readlink -f "$_f" 2> /dev/null)"
echo $_ofile
}
###
### MAIN PROGRAM
###
if [ -z "$_update_mode" ]
then
_ldd_extract "$_infile" "$_indir"
fi
if [ "$_update_mode" == "1" ]
then
_binfiles="$(find "$_indir" -type f -path "*/bin/*")"
for _binfile in $_binfiles
do
_infile=
_infile=$(_find_binfile "$_binfile")
if [ -z "$_infile" ]
then
echo "skip: $_binfile -> $_infile (not found)"
else
_ldd_extract "$_infile" "$_indir"
fi
done
fi

139
.bin/luakit-env Executable file
View File

@@ -0,0 +1,139 @@
#!/bin/sh
_dir="$1"
shift
# load config
. $HOME/.lenv
_action="$1"
shift
# validation
if [ -z "$_env" ] || [ -z "$_dir" ]
then
echo "Incomplete environment"
exit 1
fi
if [ -z "$_action" ]
then
echo "No action provided"
exit 1
fi
# now we can start...
echo "luakit-$_env: perform $_action $@ (in $_dir)" | xargs
# change into environment
mkdir -p "$_dir"
_oldpwd="$PWD"
cd "$_dir"
# perform actions
if [ "$_action" == "help" ] || [ "$_action" == "h" ]
then
echo "usage: l action [args]"
echo " actions:"
echo " make - build luakit"
echo " remake - make with -j1 (for debugging)"
echo " test [test] - run luakit test suite [specific test]"
echo " debug [luakit args] - start in gdb, stop in main"
echo " pr [numbers] - show [pull] PR from luakit/luakit repo"
echo " update - update/rebase repository"
echo " reset - recreate environment ($_dir)"
echo " diff file env - diff file with other environment"
echo " update-port - update openbsd port from last commit"
echo
fi
if [ "$_action" == "test" ]
then
export G_ENABLE_DIAGNOSTIC=1;
luajit tests/run_test.lua $@;
fi
if [ "$_action" == "make" ]
then
set -x
gmake clean
gmake options
gmake -j 8 luakit
gmake tests/util.so
fi
if [ "$_action" == "remake" ]
then
gmake -j1 luakit
fi
if [ "$_action" == "reset" ]
then
if [ "$_env" == "dev" ]
then
cd /tmp
rm -rf "$_dir"
git clone git@github.com:c0dev0id/luakit "$_dir"
cd "$_dir"
set -xe
git remote add upstream git@github.com:luakit/luakit
git fetch upstream
git checkout develop
git rebase upstream/develop
git switch -c patch
set +xe
else
cd /tmp
rm -rf "$_dir"
git clone git@github.com:luakit/luakit "$_dir"
cd "$_dir"
fi
fi
if [ "$_action" == "update" ]
then
set -xe
if [ "$_env" == "dev" ]
then
git fetch --all
git checkout develop
git rebase upstream/develop --autostash
git checkout -
else
git checkout develop
git fetch --all
git rebase origin/develop
fi
set +xe
fi
if [ "$_action" == "diff" ]
then
if test -z "$1" || test -z "$2"
then
echo "args: <file> <env>"
exit 1
fi
set -x
f="$(readlink -f $_oldpwd/$1)"
f="${f#$_dir}"
vimdiff "$_dir/$f" "${_dir%$_env}$2/$f"
fi
if [ "$_action" == "pr" ]
then
if [ -n "$1" ]
then
for pr in $@
do gh pr checkout $pr
done
else
gh pr --repo luakit/luakit list $@ | cat
fi
fi
if [ "$_action" == "update-port" ]
then
export DEVELOPMENT_PATHS=0
cd /usr/ports/mystuff/www/luakit
./update.sh
fi

2
.bin/luakit-formfiller Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/sh
sterm "vim $HOME/.local/share/luakit/forms.lua" &

View File

@@ -1,9 +1,60 @@
#!/bin/sh #!/bin/sh
set -xe # Figure out what's the best directory to put tag files in.
# This is usually the top level of the project / source directory.
# We can figure this out in a source controlled directories.
# git: the top level dir is the one that contains the .git
# directory, so we traverse the directory hierarchy backwards and
# look for it.
# cvs: the top level dir is the first dir that still contains a CVS
# directory. So we traverse back the directory hierarchy and check
# it the parent directory has no CVS directory. Then it's the current
# one.
gitdir() {
set -x
_path="$PWD"
while [ -n "$_path" ]
do [ -d "$_path/.git" ] \
&& echo "$_path" \
&& break
_path="${_path%/*}"
done
}
cvsdir() {
set -x
_path="$PWD"
while [ -n "$_path" ]
do
[ ! -d "$_path/../CVS" ] \
&& echo "$_path" \
&& break
_path="${_path%/*}"
done
}
_gitdir="$(gitdir)"
_cvsdir="$(cvsdir)"
if [ -n "$_gitdir" ]
then
_tagdir=".git"
_wrkdir="$_gitdir"
elif [ -n "$_cvsdir" ]
then
_wrkdir="$_cvsdir"
_tagdir=".tags"
else
_wrkdir=${PWD}
_tagdir=".tags"
fi
echo "Creating tags in $_wrkdir/$_tagdir"
mkdir -p "$_wrkdir/$_tagdir"
# create files list # create files list
find "${PWD}/"* -type f \ find "${_wrkdir}/"* -type f \
\( -iname "*.c" \ \( -iname "*.c" \
-o -iname "*.cc" \ -o -iname "*.cc" \
-o -iname "*.cpp" \ -o -iname "*.cpp" \
@@ -17,7 +68,7 @@ find "${PWD}/"* -type f \
-o -iname "*.pl" \ -o -iname "*.pl" \
-o -iname "*.sh" \ -o -iname "*.sh" \
-o -name "Makefile" \ -o -name "Makefile" \
\) > ${PWD}/.git/files \) > ${_wrkdir}/${_tagdir}/files
# include extra directories # include extra directories
if [ ! -z "$1" ] if [ ! -z "$1" ]
@@ -36,11 +87,11 @@ then
-o -iname "*.pl" \ -o -iname "*.pl" \
-o -iname "*.sh" \ -o -iname "*.sh" \
-o -name "Makefile" \ -o -name "Makefile" \
\) >> ${PWD}/.git/files \) >> ${_wrkdir}/${_tagdir}/files
fi fi
# create cscope database # create cscope database
cscope -qbkCRv -P${PWD} -f ${PWD}/.git/cscope.out -i${PWD}/.git/files cscope -qbkCRv -P${_wrkdir} -f ${_wrkdir}/${_tagdir}/cscope.out -i${_wrkdir}/${_tagdir}/files
# create tags file # create tags file
ectags --sort=yes \ ectags --sort=yes \
@@ -50,6 +101,6 @@ ectags --sort=yes \
--fields=+K \ --fields=+K \
--totals=yes \ --totals=yes \
--fields=fkst \ --fields=fkst \
--exclude=.git \ --exclude=${_tagdir} \
-L ${PWD}/.git/files \ -L ${_wrkdir}/${_tagdir}/files \
-f ${PWD}/.git/tags -f ${_wrkdir}/${_tagdir}/tags

32
.bin/mount-cryptoffs Executable file
View File

@@ -0,0 +1,32 @@
#!/bin/sh
_dev=${1:-sd2}
if mount | grep -q "/mnt"
then
echo "already mounted"
mount | grep "/mnt"
exit 1
fi
# check if already decrypted
_biodev=$(doas bioctl softraid0 | grep -B1 $_dev | head -1 | awk '{print $5}' \
|| exit 1)
# if not
if [ -z "$_biodev" ]
then
# decrypt
pass Local/hagibis-usb-nvme | doas bioctl -s -c C -l ${_dev}a softraid0
# and read again
_biodev=$(doas bioctl softraid0 | grep -B1 $_dev | head -1 | awk '{print $5}' \
|| exit 1)
fi
# it still might not be there (wrong password etc..)
if [ -n "$_biodev" ]
then
echo "${_dev}a attached as $_biodev"
# mount biodev
doas mount /dev/${_biodev}a /mnt \
&& echo "${_biodev}a mounted to /mnt"
fi

3
.bin/mount-exfat Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/sh -x
_dev=${1:-sd2i}
doas mount.exfat-fuse -o nodev,nosuid,noatime,uid=1000,gid=1000 /dev/${_dev} /mnt

3
.bin/mount-fat32 Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/sh -x
_dev=${1:-sd2}
doas /sbin/mount_msdos -o nodev,nosuid,noatime -u 1000 -g 1000 /dev/${_dev}i /mnt

3
.bin/mount-ffs Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/sh -x
_dev=${1:-sd2}
doas /sbin/mount_ffs /dev/${_dev}a /mnt

View File

@@ -1,2 +0,0 @@
#/bin/sh
doas /sbin/mount_msdos -o nodev,nosuid,noatime -u 1000 -g 1000

View File

@@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
if mount | fgrep '/tank/' -q if mount | fgrep -q '/tank/'
then then
echo "already mounted" echo "already mounted"
exit 1 exit 1

21
.bin/myxmenu Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/sh
get_catgirl() {
cd ~/.config/catgirl && ls * | xargs -n1 \
| while read line
do
print "\t$line\ttexec \"catgirl $line\""
done
}
IRC="$(get_catgirl)"
xmenu -i <<EOF | sh &
IRC
$IRC
Applications
IMG:./web.png Web Browser firefox
IMG:./gimp.png Image editor gimp
Terminal (xterm) xterm
Terminal (st) sterm
EOF

38
.bin/network Executable file
View File

@@ -0,0 +1,38 @@
#!/bin/sh
### DEFAULTS
### ARGUMENTS
for arg in "$@"
do
case "$arg" in
start) _start=1 ;;
stop) _stop=1 ;;
status) _status=1 ;;
route) _route=1 ;;
wifi) _wifi=1 ;;
hotspot) _hotspot=1 ;;
adhoc) _adhoc=1 ;;
esac
shift
done
### FUNCTIONS
_ifconfig() {
[ -z "$_ifdata" ] \
&& _ifdata="$(ifconfig)"
echo "$_ifdata"
}
### DATA
_interfaces="$(_ifconfig | egrep "^[a-z]" | cut -d: -f1 | egrep -v "lo0|enc0|pflog0" | xargs)"
### MAIN PROGRAM
if [ -n "$_status" ]
then
for _dev in $_interfaces
do
# something with awk
done
fi

View File

@@ -75,6 +75,7 @@ case "$EXT" in
m2ts) EXEC="mpv"; ;; m2ts) EXEC="mpv"; ;;
mp3) EXEC="mpv"; ;; mp3) EXEC="mpv"; ;;
mp4) EXEC="mpv"; ;; mp4) EXEC="mpv"; ;;
pdf) EXEC="zathura"; ;;
out) EXEC="kdump -RTf"; ;; out) EXEC="kdump -RTf"; ;;
sid) EXEC="sidplay"; ;; sid) EXEC="sidplay"; ;;
torrent) EXEC="aria2c"; ;; torrent) EXEC="aria2c"; ;;

35
.bin/obsd-route Executable file
View File

@@ -0,0 +1,35 @@
#!/bin/sh
[ $(id -u) -ne 0 ] && echo "root?" && exit 0
usage() {
echo "obsd-route [start,stop]"
exit 0
}
do_start() {
set -x
sysctl net.inet.ip.forwarding=1
ifconfig trunk0 destroy
ifconfig qwx0 inet autoconf
ifconfig re0 inet 192.168.23.1 netmask 255.255.255.0
rcctl enable dhcpd
rcctl set dhcpd flags re0
rcctl start dhcpd
}
do_stop() {
set -x
sysctl net.inet.ip.forwarding=0
ifconfig qwx0 -inet
ifconfig re0 -inet
rcctl stop dhcpd
rcctl disable dhcpd
sh /etc/netstart
}
case $1 in
start) do_start; ;;
stop) do_stop; ;;
*) usage;
esac

View File

@@ -7,6 +7,9 @@ trap abort 1 2 3 6 9 11
abort() { echo "Abort with >$0 $ARGS< on $(date)" >> /tmp/obsdmake.log; } abort() { echo "Abort with >$0 $ARGS< on $(date)" >> /tmp/obsdmake.log; }
JOBS="${JOBS:=$(sysctl -n hw.ncpuonline)}" JOBS="${JOBS:=$(sysctl -n hw.ncpuonline)}"
JOBS=1
LOG="/home/sdk/obsdmake.log"
export CCACHE_DIR="/var/ccache" export CCACHE_DIR="/var/ccache"
export CCACHE_SLOPPINESS="locale,time_macros,random_seed,file_stat_matches,pch_defines" export CCACHE_SLOPPINESS="locale,time_macros,random_seed,file_stat_matches,pch_defines"
@@ -24,12 +27,13 @@ if [ -z "$1" ]; then
exit 2 exit 2
fi fi
echo "Start with >$0 $ARGS< on $(date)" >> /tmp/obsdmake.log echo "Start with >$0 $ARGS< on $(date)" >> $LOG
doas mkdir -p /usr/obj /usr/xobj doas mkdir -p /usr/obj /usr/xobj
doas chown build /usr/obj /usr/xobj doas chown build /usr/obj /usr/xobj
mkkernel() { mkkernel() {
echo "Step: kernel start ($(date))" >> $LOG
set -xe set -xe
cd /sys/arch/$(machine)/compile/GENERIC.MP cd /sys/arch/$(machine)/compile/GENERIC.MP
doas make clean doas make clean
@@ -39,9 +43,11 @@ mkkernel() {
doas make install doas make install
doas what /bsd doas what /bsd
doas ln -f /bsd.booted /bsd.backup doas ln -f /bsd.booted /bsd.backup
echo "Step: kernel done ($(date))" >> $LOG
} }
mkbase() { mkbase() {
echo "Step: base start ($(date))" >> $LOG
set -xe set -xe
cd /usr/src cd /usr/src
doas make obj doas make obj
@@ -50,9 +56,11 @@ mkbase() {
doas sysmerge doas sysmerge
cd /dev cd /dev
doas ./MAKEDEV all doas ./MAKEDEV all
echo "Step: base done ($(date))" >> $LOG
} }
mkxenocara() { mkxenocara() {
echo "Step: xenocara start ($(date))" >> $LOG
set -xe set -xe
doas chown -R sdk /usr/xenocara doas chown -R sdk /usr/xenocara
cd /usr/xenocara cd /usr/xenocara
@@ -61,9 +69,11 @@ mkxenocara() {
doas make obj doas make obj
doas make -j${JOBS} build doas make -j${JOBS} build
doas make install doas make install
echo "Step: xenocara done ($(date))" >> $LOG
} }
mkrelease() { mkrelease() {
echo "Step: release start ($(date))" >> $LOG
set -xe set -xe
doas mkdir -p /data/{OpenBSD,Release} doas mkdir -p /data/{OpenBSD,Release}
doas chown -R build /data doas chown -R build /data
@@ -86,6 +96,7 @@ mkrelease() {
cd /usr/src/distrib/$(machine)/iso cd /usr/src/distrib/$(machine)/iso
doas make doas make
doas make install doas make install
echo "Step: release done ($(date))" >> $LOG
} }
kernelclean() { kernelclean() {
@@ -127,5 +138,5 @@ case "$1" in
all) mkkernel; mkbase; mkxenocara; ;; all) mkkernel; mkbase; mkxenocara; ;;
esac esac
echo "Finished with >$0 $ARGS< on $(date)" >> /tmp/obsdmake.log echo "Finished with >$0 $ARGS< on $(date)" >> $LOG
sync sync

26
.bin/osmc Executable file
View File

@@ -0,0 +1,26 @@
#!/bin/sh
USBDISK=/mnt/1TB
case "$1" in
mount) shift; ssh -tt osmc "sudo /sbin/cryptdisks_start usbdisk" \
&& ssh osmc "sudo mount /mnt/1TB" ;;
put|push) shift; rsync -rv --progress --append-verify "$@" osmc:$USBDISK/ ;;
df) shift; ssh osmc "df -h $USBDISK" ;;
ls) shift; ssh osmc "cd $USBDISK && ls $@ | grep -v lost+found" ;;
lls) shift; ssh osmc "cd $USBDISK && ls -lh | grep -v lost+found" ;;
del) shift; ssh osmc "cd $USBDISK && rm -v $@" ;;
ren) shift; ssh osmc "cd $USBDISK && mv \"$1\" \"$2\"" ;;
at) shift; ssh -tt osmc "tmux at" ;;
*) echo "usage: osmc <command> <args>"
echo " mount - mount USB disk"
echo " df - show disk space allocation"
echo " ls - list files"
echo " lls - list files with details"
echo " put <files> - copy files to USB disk"
echo " ren <old> <new> - rename file"
echo " del <files> - delete file"
echo " at - attach to tmux session"
exit 2
;;
esac

169
.bin/pkg-depends Executable file
View File

@@ -0,0 +1,169 @@
#!/bin/sh
# lazy config
_sqlports="/usr/local/share/sqlports"
_pkgpath="$(head -1 /etc/installurl)/$(uname -r)/packages/$(uname -m)"
# parameters can be freely combined
_usage() {
echo "usage: pkg-depends [options] <pkgpath>"
echo "options: -r - list run dependencies (default)"
echo " -l - list lib dependencies (default)"
echo " -b - list build dependencies"
echo " -t - list test dependencies"
echo " -p - show packges names (default)"
echo " -P - show port paths"
echo " -d <dir> - download packages to <dir>"
echo
echo "Only one flavor / subpackage in pkgpath(7) is supported."
exit 2
}
while getopts rlbtpPd: arg
do
case $arg in
l) _deps="$_deps 0" ;;
r) _deps="$_deps 1" ;;
b) _deps="$_deps 2" ;;
t) _deps="$_deps 3" ;;
p) _showmode=$(( _showmode + 1 )) ;;
P) _showmode=$(( _showmode + 2 )) ;;
d) _dldir=$OPTARG ;;
h) _usage ;;
?) _usage ;;
esac
done
shift $(($OPTIND - 1))
[ -z "$1" ] \
&& _usage
if [ ! -f "$_sqlports" ]
then
echo "$_sqlports not found. Install \"sqlports\" to use this script."
exit 1
fi
### FUNCTIONS
# a little helper in case no pkgpath is provided
_do_pkg() {
echo "pkg-depends needs pkgpath(7) as argument, pkg_info -P can help."
echo "Here, I'm calling it for you:"
echo
echo "$ pkg_info -P $1"
pkg_info -P "$1"
exit 0
}
_do_sql() {
# XXX: This lists all dependencies for the dependencies for the
# dependencies. I haven't encountert an endless loop here (yet?).
# I guess sqlite takes care or that?
# I'm sure the performance can be improved by not using the big
# ports view to grab the pkgname. But it's late and it works and
# this is a problem for another day.
_query="
WITH RECURSIVE pkg(x) AS (
SELECT \"$1\"
UNION
SELECT distinct dependspath FROM canonical_depends
JOIN pkg ON fullpkgpath=x WHERE type in ($2)
) SELECT x, fullpkgname FROM pkg
JOIN ports ON fullpkgpath=x;
"
echo "SQL QUERY: $_query" > $HOME/pkg-depends.log
echo "RESULT:" >> $HOME/pkg-depends.log
sqlite3 "$_sqlports" "$_query" | tee -a $HOME/pkg-depends.log
}
_handle_list() {
# build the comma sparated list that descibes the types
# to include in the list. Used in the sql query.
# _deps are set in getops, with a leading space when 0
# is not set. FIXME: I'm sure there's a better way to do this.
if [ -z "$_deps" ]
then
_deps="0,1"
else
_deps="$(echo "$_deps" \
| tr -s " " \
| sed 's/^ //g' \
| tr ' ' ',')"
fi
# download mode: create directory provided in -d <dir>
if [ -n "$_dldir" ]
then
mkdir -p "$_dldir"
fi
echo "Figuring out recursive dependencies, this may take some time..."
# FIXME: even though the list ist sorted -u this is only true for
# pkgpath, as textproc/libical and textproc/libical,-main are the
# going to be the same package. Simply stripping off all ,-main
# could fix it.. but it doesn't feel right.
_do_sql "$1" "$_deps" | sort -u | while read line
do
_portpath=$(echo "$line" | cut -d"|" -f1)
_pkgname=$(echo "$line" | cut -d"|" -f2)
# download mode: -d <dir>
if [ -n "$_dldir" ]
then
_extra="(downloading)"
fi
# showmode:
# unset: shows pkgpath and pkgname
# 1: shows pkgname only
# 2: shows pkgpath only
# 3: equals unset # FIXME: set 3 as default and don't handle unset.
# default || both on
if [ -z "$_showmode" ] || [ "$_showmode" == "3" ]
then
echo "$_portpath ($_pkgname) $_extra"
fi
# pkgname only
if [ "$_showmode" == "1" ]
then
echo "$_pkgname $_extra"
fi
# portpath only
if [ "$_showmode" == "2" ]
then
echo "$_portpath $_extra"
fi
# download mode: download file from mirror
# note: this needs sqlports information and the mirror to be
# in sync, which only the case on -release.
# FIXME: figure out a way to do this in snaps.
# Naive idea: cut off the version, get index list from mirror with
# match agains the non-version name and download everything found.
if [ -n "$_dldir" ]
then
ftp -MV -C -o $_dldir/$_pkgname.tgz $_pkgpath/$_pkgname.tgz
fi
done
if [ -n "$_dldir" ]
then
# XXX: Are both variables needed?
echo "Set the following environmane variables to enable offline installation:"
echo "$ export TRUSTED_PKG_PATH=\"$(readlink -f "$_dldir")\""
echo "$ export PKG_PATH=\"$(readlink -f "$_dldir")\""
# FIXME: name the package that has been downloaded. But to translate $1
# to the package name, another sqlports db call would be necessary.
# There is also pkg_info -e ..., but that only works for alread installed
# packages.
echo "$ pkg_add <package>"
fi
}
### MAIN PROGRAM :)
case "$1" in
*/*) _handle_list "$1" ;;
*) _do_pkg "$1" ;;
esac

View File

@@ -1,6 +1,9 @@
#!/bin/sh -x #!/bin/sh -x
cd /usr/ports cd /usr/ports
doas rm -rf pobj/* plist logs packages bulk update distfiles/* doas rm -rf pobj/* plist logs packages bulk update
case "$1" in
-a) doas rm -rf distfiles/* ;;
esac
mkdir -p plist logs packages bulk update mkdir -p plist logs packages bulk update
doas make fix-permissions doas make fix-permissions

View File

@@ -1,12 +1,17 @@
#!/bin/sh #!/bin/sh -x
if [ -z "$1" ] if [ -z "$1" ]
then then
echo "usage: port-search <file pattern> <search term>" echo "usage: port-search [file pattern] <search term>"
exit 2 exit 2
fi fi
type="$1" if [ -n "$2" ]
shift then
_filter="-iname *$1*" \
_term="$2"
else
_term="$1"
fi
find /usr/ports/ \ find /usr/ports/ \
-not \( -path "/usr/ports/pobj" -prune \ -not \( -path "/usr/ports/pobj" -prune \
@@ -16,5 +21,5 @@ find /usr/ports/ \
-o -path "*/CVS" -prune \ -o -path "*/CVS" -prune \
\) \ \) \
-type f \ -type f \
-iname "$type" \ $_filter \
-exec ugrep -F -- "$@" {} + -exec ugrep -i -F -- "$_term" {} +

24
.bin/rec_scr_hw_noaudio.sh Executable file
View File

@@ -0,0 +1,24 @@
#!/bin/sh
set -e
# configuration
_vidfile="/home/sdk/rec-screen.mkv"
_outfile="/home/sdk/rec-encoded-$(date "+%Y-%m-%d_%H%M%S").mp4"
_res="2880x1800"
_fps="60"
printf 'Press q to stop.\n'
set -x
ffmpeg -y -loglevel error -hide_banner \
-vaapi_device /dev/dri/renderD128 \
-framerate ${_fps} \
-f x11grab \
-video_size ${_res} \
-i :0 \
-vf 'hwupload,scale_vaapi=format=nv12' \
-c:v h264_vaapi \
-qp 24 \
-framerate ${_fps} \
"${_outfile}"

69
.bin/rtservermon.pl Executable file
View File

@@ -0,0 +1,69 @@
#!/usr/bin/perl
use strict;
use warnings;
#
# ONLY OpenBSD modules included with the default installation are permitted!
#
use HTTP::Tiny;
use Net::Ping;
use Time::HiRes;
# Configuration hash (editable)
my %config = (
'timeout' => 0.20, # How long to wait before giving up on server response, in seconds
'debug' => 1, # Debug output?
'top' => 3, # How many entries to return?
'protocol' => 'tcp', # tcp, udp, icmp, et al
'port' => 'http', # (used in getservbyname sub)
);
# hash to store servers and response times to protocol/port requests
my %serverstats;
# create HTTP::Tiny instance
my $http = HTTP::Tiny->new;
# Get a list of all current OpenBSD FTP servers
my $response = $http->get('http://ftp.eu.openbsd.org/pub/OpenBSD/ftplist');
die "Failed!\n" unless $response->{success};
# Iterate through server list and get TCP/80 response time in ms
foreach my $line (split("\n", $response->{content})) {
if ($line !~ /(cdn)/) {
if ($line =~ /(http:\/\/)(.+?)(\/\S+)/) {
my $response = &httping($2);
$serverstats{$1.$2.$3} = $response if ($response);
}
}
}
# Sort & print servers by response time in ms
my $i = 0;
foreach my $key (sort {$serverstats{$a} <=> $serverstats{$b} } keys %serverstats) {
$i++;
print "$key\n";
last if $i eq $config{'top'};
}
#
# Ping TCP/80 and return response time or 0 if unresponsive + some diagnostic output
#
sub httping ($) {
my $host = shift;
my $ping = Net::Ping->new($config{'protocol'});
$ping->hires();
$ping->{port_num} = getservbyname($config{'port'}, $config{'protocol'});
print ("Trying $host... ") if $config{'debug'};
my ($retval, $duration, $ip) = $ping->ping($host, $config{'timeout'});
$ping->close();
$duration = int($duration * 1000);
if ($retval) {
print ("$duration ms\n") if $config{'debug'};
return $duration;
} else {
print ("unresponsive\n") if $config{'debug'};;
return 0;
}
}

2
.bin/samba Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/sh
doas doas rcctl -f $1 smbd nmbd;

View File

@@ -1,3 +1,80 @@
#!/bin/sh #!/bin/sh
[ -z $1 ] && doas wsconsctl -n display.brightness \
|| doas wsconsctl display.brightness=$1 # devices
_primary=$(xrandr | grep -v ^Screen | head -1 | cut -d" " -f1)
_max_res=$(xrandr | grep "^ " | head -1 | xargs | cut -d" " -f1)
_con_dev=$(xrandr | grep " connected" | grep -v "$_primary" | cut -d" " -f1 | xargs)
_dis_dev=$(xrandr | grep "disconnected" | cut -d" " -f1 | xargs)
if [ "$1" == "auto" ]
then
xrandr --output $_primary --auto
fi
if [ "$1" == "mirror" ]
then
for _dev in $_con_dev
do
xrandr --output $_dev --same-as $_primary
done
fi
_loop() {
set -x
for _dev in $1
do xrandr --output $_dev $2
done
}
[ "$1" == "left" ] \
&& _loop "$_con_dev" "--left-of $_primary"
[ "$1" == "right" ] \
&& _loop "$_con_dev" "--right-of $_primary"
[ "$1" == "above" ] \
&& _loop "$_con_dev" "--above $_primary"
[ "$1" == "auto" ] \
&& _loop "$_con_dev $_primary" "--auto"
[ "$1" == "off" ] \
&& _loop "$_con_dev" "--off"
[ "$1" == "fullhd" ] \
&& xrandr --output $_primary --mode "1920x1080"
[ "$1" == "hd" ] \
&& xrandr --output $_primary --mode "1280x720"
[ "$1" == "max" ] \
&& xrandr --output $_primary --mode "$_max_res"
case "$1" in
[0-9]*) doas wsconsctl display.brightness=$1 ;;
esac
[ "$1" == "r" ] && [ -n "$2" ] \
&& xrandr --output $_primary --mode "$2"
if [ -z "$1" ]
then
echo "usage: res [mode]"
echo " auto - sets prefered mode for all connected displays"
echo " left - put screen left of primary screen"
echo " right - put screen right of primary screen"
echo " above - put screen above of primary screen"
echo " off - turn all connected screens off (except primary)"
echo " fullhd - set primary display resolution to FullHD (1920x1080)"
echo " hd - set primary display resolution to HD (1280x720)"
echo " max - set primary display to highest resolution ($_max_res)"
echo " r <res> - set primary display resolution"
echo " b <%> - display / set screen brightness"
echo
echo "Primary: $_primary"
echo "Connected: $_con_dev"
echo "Brightness: $(doas wsconsctl -n display.brightness)%"
echo
fi
exit 0

View File

@@ -2,6 +2,9 @@
. ${HOME}/.bin/_config . ${HOME}/.bin/_config
unset QT_FONT_DPI
unset GDK_DPI_SCALE
trap cleanup 1 2 3 6 trap cleanup 1 2 3 6
cleanup() { rm -f "$file"; } cleanup() { rm -f "$file"; }

97
.bin/subsonic Executable file
View File

@@ -0,0 +1,97 @@
#!/bin/sh
# subsonic
alias subsonic-cli="\subsonic-cli -c $HOME/.subsonic-cli.conf"
subsonic-play() {
# $1 songId
for song in $@
do
echo $song > /tmp/.playing
subsonic-cli stream -p id $song \
| mpv --force-window=no --loop=no - || exit 0
done
}
subsonic-random() {
while true;
do
echo "Fetching moar dataaa.."
subsonic-play $(subsonic-cli getRandomSongs \
| jq -r '.randomSongs[][].id')
done
}
subsonic-favorites() {
while true;
do
echo "Fetching moar dataaa.."
subsonic-play $(subsonic-cli getStarred \
| jq -r '.starred[][].id' \
| sort -r)
done
}
subsonic-search() {
{
echo "|ALBUMID|ID|ALBUM|ARTIST|TITLE|GENRE|"
printf "|%s|%s|%s|%s|%s|%s|\n" "--------------------------------"\
"--------------------------------"\
"--------" "--------" "--------" "--------"
subsonic-cli search3 \
-p songcount 200 \
-p query "$@" \
| jq -r '.searchResult3[][]|select(.contentType!=null)|[.albumId,.id,.album,.title,.artist,.genre]' \
| tr -d '", ' \
| awk '/^\[/ { S++ } \
/^\]/ { S-- } \
S==0 { NR=0 } \
NR==2 { AID=$0 } \
NR==3 { ID=$0 } \
NR==4 { ALBUM=$0 } \
NR==5 { TITLE=$0 } \
NR==6 { ARTIST=$0 } \
NR==7 { GENRE=$0 } \
NR==0 { printf("|%s|%s|%s|%s|%s|%s|\n", AID, ID, ALBUM, ARTIST, TITLE, GENRE) }'
} | column -s'|' -t
}
subsonic-star() {
[ -f /tmp/.playing ] \
&& subsonic-cli star -p id $(cat /tmp/.playing | tail -1) \
|| echo bruh.
}
subsonic-unstar() {
[ -f /tmp/.playing ] \
&& subsonic-cli unstar -p id $(cat /tmp/.playing | tail -1) \
|| echo bruh.
}
subsonic-download() {
# $1 albumId
NAME=$(subsonic-cli getAlbum -p id $1 \
| jq -r '.album.artist,.album.name' | xargs | tr ' ' '-')
printf "Downloading to %s/subsonic-download/%s.zip\n" "$HOME" "$NAME"
mkdir -p "$HOME/subsonic-download"
subsonic-cli download -p id $1 | pv > "$HOME/subsonic-download/$NAME.zip"
}
if [ -z $1 ]
then
cat <<"EOF"
usage: subsonic <command> <args>
play <song id> - play song with id
download <album id> - download album with id
[un]star - [un]star currently playing song
search <term> - show song/album for term
favorites - play starred songs
random - play random songs
EOF
else
subsonic-$1 $2
fi

7
.bin/tailscale-tunnel Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/ksh
# doas tailscale up --auth-key=tskey-auth-kx3Lf18kgg11CNTRL-5QJ7tUCJ8KAoPqVtJKY6MAzghyuCoaR9F
doas tailscale up \
--reset \
--advertise-exit-node \
--accept-routes \
--accept-dns=true

6
.bin/tailscale-tunnel-client Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/ksh
# doas tailscale up --auth-key=tskey-auth-kx3Lf18kgg11CNTRL-5QJ7tUCJ8KAoPqVtJKY6MAzghyuCoaR9F
doas tailscale up \
--reset \
--accept-dns=true \
--exit-node=dalek

View File

@@ -1,13 +1,22 @@
#!/bin/sh #!/bin/sh
. $HOME/.bin/_config . $HOME/.bin/_config
[ -d "$1" ] || ( printf "Usage: backup <target>\n" && exit 2; ) _target=$(readlink -f "$1" 2> /dev/null)
[ ! "$_target" ] \
&& printf "Usage: backup <target>\n" \
&& exit 2;
print "pass Internet/Tarsnap.key > /root/tarsnap.key ..."
pass Internet/Tarsnap.key | doas tee /root/tarsnap.key > /dev/null
doas chown root:sdk /root/tarsnap.key
doas chmod 640 /root/tarsnap.key
doas chmod 750 /root
print "Tarsnap Backup:" print "Tarsnap Backup:"
_target=$(readlink -f "$1")
_key=$(pwgen -n1 8) _key=$(pwgen -n1 8)
_date=$(date "+%Y-%m-%d %H:%M") _date=$(date "+%Y-%m-%d %H:%M")
_host=$(uname -n) _host=$(uname -n)
doas tarsnap --humanize-numbers --checkpoint-bytes 52428800 --exclude "*/.git/*" -cvf "$_host: $_target $_date ($_key)" "$_target" doas tarsnap --humanize-numbers --checkpoint-bytes 52428800 --exclude "*/.git/*" -cvf "$_host: $_target $_date ($_key)" "$_target"

38
.bin/tarsnap-restore Executable file
View File

@@ -0,0 +1,38 @@
#!/bin/sh
. $HOME/.bin/_config
print "Tarsnap Restore:"
if [ -z "$1" ]; then
doas tarsnap --list-archives | sort
printf "Usage: restore <key_id>\n"
exit 2
fi
_backup="$(doas tarsnap --list-archives | grep "$1")"
if [ -z "$_backup" ]; then
print "No backup with key id $1 found."
exit 1
fi
print "Found Backup: $_backup"
mkdir -p "restore_$1"
print "Extracting to: $(readlink -f $PWD/restore_$1)"
if [ -f "restore_$1/.done" ]
then
print "Skipping, because restore_$1/.done file exists."
else
doas tarsnap -tf "$_backup" \
| xargs -P 50 -n 1 -t \
doas tarsnap --humanize-numbers --resume-extract --chroot -xf "$_backup" -C "restore_$1" --
if [ $? -eq 0 ]
then
print "Data restored in $(readlink -f "restore_$1")"
touch "restore_$1/.done"
else
print "Restore aborted..."
fi
fi
print ""

10
.bin/umount-cryptoffs Executable file
View File

@@ -0,0 +1,10 @@
#!/bin/sh
_dev=${1:-sd3}
doas umount /mnt 2>&1 | grep -q busy && echo "/mnt is busy" && exit 1
_biodev=$(doas bioctl softraid0 | grep -C1 sd3 | grep CRYPTO | awk '{ print $5 }')
if [ -n "$_biodev" ]
then
doas bioctl -d ${_biodev} && echo "bioctl: $_dev detached"
else
echo "bioctl: $_dev: currently not attached"
fi

137
.bin/update-adlist Executable file
View File

@@ -0,0 +1,137 @@
#!/bin/sh -e
trap _restore_all 1 2 3 6
# list of filenames can can be fetched from $_url
_list=/etc/unwind/blocklistproject.txt
_url=https://blocklistproject.github.io/Lists/alt-version
# download blocklists here
_dir=/etc/unwind/lists
# combined, sorted and filtered list of all lists configured in $_list
# configure in /etc/unwind.conf:
# block list "/etc/unwind/_assembled.txt" log
_unwind_blocklist="/etc/unwind/_assembled.txt"
if [ ! -f $_list ]
then
echo "Creating new adlist /etc/unwind/blocklistproject.txt:"
doas mkdir -p $_dir
doas tee $_list <<EOF
## from https://github.com/blocklistproject/Lists
## ## => comment
## # => disabled list (will be deleted if present)
abuse-nl.txt
adobe-nl.txt
ads-nl.txt
basic-nl.txt
crypto-nl.txt
drugs-nl.txt
#everything-nl.txt
facebook-nl.txt
fortnite-nl.txt
fraud-nl.txt
gambling-nl.txt
malware-nl.txt
phishing-nl.txt
piracy-nl.txt
porn-nl.txt
ransomware-nl.txt
redirect-nl.txt
scam-nl.txt
smart-tv-nl.txt
tiktok-nl.txt
torrent-nl.txt
tracking-nl.txt
twitter-nl.txt
vaping-nl.txt
whatsapp-nl.txt
youtube-nl.txt
EOF
fi
_restore_all() {
echo "Signal received, aborting..."
for _f in $_dir/*.old
do
echo "Restore: $(basename $_f)"
doas mv -f "$_f" "${_f%%.old}"
done
_assemble
_restart_unwind
exit 1
}
_backup() {
_f=$(basename "$1")
if [ -f "$_dir/$_f" ]
then
echo "Backup: $_f -> $_f.old"
doas mv -f "$_dir/$_f" "$_dir/$_f.old"
fi
}
_restore() {
_f=$(basename "$1")
if [ -f "$_dir/$_f.old" ]
then
echo "Restore: $_f.old -> $_f"
doas mv -f "$_dir/$_f" "$_dir/$_f.old"
fi
}
_download() {
echo "Download: $_file"
doas ftp -V -o "$_dir/$_file" "$_url/$_file" > /dev/null \
&& doas rm -f "$_dir/$_file.old"
}
_disabled() {
if echo "$1" | grep -q "^#"
then
_f=$(basename "$1" | tr -d '# ')
echo "Skip (disabled): $_f"
doas rm -f $_dir/$_f
return 0
fi
return 1
}
_domainfilter() {
# chain grep commands used in assemble pipe
grep -Ev "torrent|tattoo|xhamster|xvideos|porn|motherless|redgifs" \
| grep -Ev "whatsapp\.net|whatsapp\.com|instagram\.com" \
| grep -Ev "adobe\.com|adobelogin\.com" \
| grep -Ev "microsoft\.com|archive\.org|sony\.com|playstation|psn|fotostelvio"
}
_assemble() {
echo "Assemble blocklist: $_unwind_blocklist"
cat $_dir/*.txt \
| tr -d " " \
| grep -v '^#' \
| grep -v '^-' \
| grep -v '^$' \
| cut -d "#" -f1 \
| sed 's/\.$//g' \
| _domainfilter \
| doas sort -uo $_unwind_blocklist
}
_restart_unwind() {
doas rcctl restart unwind
}
for _file in $(grep -v "^##" $_list \
| cut -d "#" -f1 \
| xargs)
do
if ! _disabled $_file
then
_backup $_file
_download || _restore
fi
done
_assemble
_restart_unwind

View File

@@ -1,6 +1,6 @@
#!/bin/ksh #!/bin/ksh
FILE="$HOME/.ksh.complete" FILE="$HOME/.kshrc.autocomplete"
rm -f "${FILE}" rm -f "${FILE}"
@@ -37,12 +37,27 @@ add "set -A complete_kill_1 -- " "-9 -HUP -INFO -KILL -TERM"
# #
add "set -A complete_ifconfig_1 -- " "$(ifconfig | grep ^[a-z] | cut -d: -f1)" add "set -A complete_ifconfig_1 -- " "$(ifconfig | grep ^[a-z] | cut -d: -f1)"
#
# manpages
#
S1="$(man -s 1 -k any= | cut -d"(" -f1 | tr -d "," | xargs)"
S2="$(man -s 2 -k any= | cut -d"(" -f1 | tr -d "," | xargs)"
S3="$(man -s 3 -k any= | cut -d"(" -f1 | tr -d "," | xargs)"
S4="$(man -s 4 -k any= | cut -d"(" -f1 | tr -d "," | xargs)"
S5="$(man -s 5 -k any= | cut -d"(" -f1 | tr -d "," | xargs)"
S8="$(man -s 8 -k any= | cut -d"(" -f1 | tr -d "," | xargs)"
add "set -A complete_man_1 -- " "$S1 $S5 $S8"
# #
# AMUSED # AMUSED
# #
ARGS="add flush jump load monitor next pause play prev repeat restart show status stop toggle" ARGS="add flush jump load monitor next pause play prev repeat restart show status stop toggle"
add "set -A complete_amused_1 -- " "$ARGS" add "set -A complete_amused_1 -- " "$ARGS"
add "set -A complete_l_1 -- " "make remake test debug pr update reset diff update-port"
add "set -A complete_upload_1 -- " "rm rml ls last ren renl fixl sh ksh txt log gz tgz"
# #
# GOT # GOT
# #

10
.bin/update-luakit-adlist Executable file
View File

@@ -0,0 +1,10 @@
#!/bin/sh -xe
for list in easylist/easylist \
easylist/easyprivacy \
easylist/fanboy-social \
easylistgermany/easylistgermany
do
ftp -o $HOME/.local/share/luakit/adblock/$(basename $list).txt \
https://easylist.to/${list}.txt
done

14
.bin/update-mystuff Executable file
View File

@@ -0,0 +1,14 @@
#!/bin/sh -xe
mystuff="
/usr/ports/mystuff/x11/st-sdk
/usr/ports/mystuff/sysutils/libtree
/usr/ports/sysutils/tarsnap
"
for p in $mystuff
do
cd $p
make clean=all
make reinstall
done

39
.bin/update-pim-all Executable file
View File

@@ -0,0 +1,39 @@
#/bin/sh -xe
. ~/.bin/_config
needs vdirsyncer-- mu-- isync-- git-- p5-iCal-Parser-- remind--
# snapshot
cd /home/sdk/.reminders
git add *
git commit -m "Update $(date +"%Y-%m-%d %H:%M:%S")" || true
# copy uugrn calendard to dalek
scp -q vorstand@vorstand.uugrn.org:private/Kalender/uugrn.rem \
sdk@home.codevoid.de:.reminders/uugrn.rem
# copy all calendars from dalek to local
scp -q sdk@home.codevoid.de:.reminders/\*.rem \
/home/sdk/.reminders/
# download vcal/vcard from icloud / radical
vdirsyncer sync
# create import.rem from ical events (XXX fix this mess)
find ~/.isync -name "*.ics" -exec cat {} + \
| ical2rem --no-todos \
| fgrep -v "REM MSG" \
| sed 's,\\n, ,g' \
| tr -d '\' \
| sed 's/ / /g' \
> /home/sdk/.reminders/import.rem
# create abook addressbook
cat /home/sdk/.isync/contacts/*.vcf \
| abook --convert --informat vcard --outformat abook \
> /home/sdk/.abook/addressbook
# sync email to offline
mbsync -a
# index email
mu index

View File

@@ -1,25 +1,267 @@
#!/bin/sh -e #!/bin/sh -e
file="$1" # manage files in a webroot
# needs:
# - sh: cp, rm, mv, echo, basename, dirname
# - openssh: ssh, scp
# - coreutils: chmod, sed, tail
# - archivers: gzip, tar
# - xclip
[ -z $file ] \ ###
&& file="$(find $PWD $HOME $HOME/Downloads -maxdepth 2 -type f \ ### CONFIGURATION
| fgrep -v "/." \ ###
| sort -u \
| fzf -e -x -i)"
[ -z $file ] \ # remote patch uploaded files should go
&& exit 0 _rpath="/home/www/htdocs/ptrace/paste"
scp "$file" \ # web url where the uploaded files can be accessed
sdk@home.codevoid.de:make-web/src/paste/ _weburi="https://ptrace.org"
ssh sdk@home.codevoid.de \ # ssh user@host
"cd ~/make-web && make install" _sshhost="sdk@codevoid.de"
echo "https://ptrace.org/$(basename "$file")" \ # permissions (for the fixl command)
| sed 's/ /%20/g' \ _chown="sdk:www"
| xclip -f -r _chmod="u+rw,g+r"
echo ###
### SET ARGUMENT SWITCHES
###
for arg in "$@"
do
case "$arg" in
# extensions
sh) _ext=".sh" ;;
ksh) _ext=".ksh" ;;
txt) _ext=".txt" ;;
log) _ext=".log" ;;
# archive mode
gz) _gz=1 ;;
tgz) _tgz=1 ;;
# commands
rm) _rm=1 ;;
rml) _rmlast=1 ;;
ls) _ls=1 ;;
l|last) _last="-1" ;;
-[0-9]*) _last="$arg" ;;
fixl) _fixperm=1 ;;
ren|mv) _mv=1 ;;
renl|mvl) _mvlast=1 ;;
-h) ;; # swallow
*) break; ;;
esac
shift;
done
###
### FUNCTIONS
###
# fetches remote file list
remote_list() {
ssh $_sshhost \
"cd $_rpath/ \
&& ls -1tr"
}
# formats file list output
remote_list_print() {
while read f
do
echo "$_weburi/$(echo "$f" \
| sed 's/ /%20/g') ($f)"
done
}
copy_and_print() {
echo "$_weburi/$(basename "$1")" \
| sed 's/ /%20/g' \
| xclip -f -r
echo
}
###
### MAIN PROGRAM
###
# HANDLE CASE: "standard input"
# upload with provided or generated filename
if [[ ! -t 0 ]]
then
fname="$1"
[ -z "$fname" ] \
&& fname="$(date +"%Y-%m-%d_%H%M%S").txt"
cat - | ssh $_sshhost "cat - > \"$_rpath/$fname\""
copy_and_print "$fname"
exit 0
fi
# HANDLE CASE: "list all remote files"
if [ -n "$_ls" ]
then
remote_list \
| remote_list_print
exit 0
fi
# HANDLE CASE: "list last N remote files"
if [ -n "$_last" ]
then
remote_list \
| tail $_last \
| remote_list_print
exit 0
fi
# HANDLE CASE: rename remote file
if [ -n "$_mv" ]
then
_arg1=$(basename "$1")
_arg2=$(basename "$2")
ssh $_sshhost \
"cd $_rpath/ \
&& mv -v \"$_arg1\" \"$_arg2\""
echo "$_arg2" | remote_list_print
exit 0
fi
# HANDLE CASE: rename the last uploaded remote file
if [ -n "$_mvlast" ]
then
_arg1=$(basename "$1")
lastfile="$(remote_list | tail -1)"
ssh $_sshhost \
"cd $_rpath/ \
&& mv -v \"$lastfile\" \"$_arg1\""
echo "$_arg1" | remote_list_print
exit 0
fi
# HANDLE CASE: delete remote file
if [ -n "$_rm" ]
then
for file in "$@"
do
ssh $_sshhost \
"cd $_rpath/ \
&& rm -v \"$(basename "$file")\"" \
|| true
done
exit 0
fi
# HANDLE CASE: delete last uploaded remote file
if [ -n "$_rmlast" ]
then
lastfile="$(remote_list | tail -1)"
echo "rm $lastfile"
ssh $_sshhost \
"cd $_rpath/ \
&& rm -f \"$lastfile\"" \
|| true
exit 0
fi
# HANDLE CASE: fix permission of last file
if [ -n "$_fixperm" ]
then
lastfile="$(remote_list | tail -1)"
echo "Fixing: $lastfile"
ssh $_sshhost "cd $_rpath/; \
chown $_chown \"$lastfile\"; \
chmod $_chmod \"$lastfile\"; \
ls -lh \"$lastfile\""
exit 0
fi
# HANDLE CASE: upload of files and folders
if [ $# -gt 0 ]
then
for item in "$@"
do
# the whole handling shall run in a subshell so all variables
# are reset when we leave the scope. Note, that this requires
# us to "return", instead of "continue" skip to the next loop
# iteration
(
[ ! -e "$item" ] \
&& echo "File or directory not found: $item" \
&& return
# target filename
file="$(basename "$item")$_ext"
# CASE "file" "no archive mode"
if [ -f "$item" ] && [ -z "$_tgz" ] && [ -z "$_gz" ]
then
echo "Uploading $item as $file"
scp -q "$item" $_sshhost:"$_rpath/$file"
copy_and_print "$file"
return
fi
# CASE "folder"
[ -d "$item" ] && _tgz=1
# CASE "tgz archive mode"
if [ -n "$_tgz" ]
then
file="$file.tgz"
echo "Uploading $item as $file"
# moving closer to the item to not archive the whole path
cd $(dirname "$item")
tar czf - "$(basename "$item")" \
| ssh $_sshhost "cat - > \"$_rpath/$file\""
copy_and_print "$file"
return
fi
# CASE "gz archive mode"
if [ -f "$item" ] && [ -n "$_gz" ]
then
file="$file.gz"
echo "Uploading \"$item\" as \"$file\""
cat "$item" | gzip \
| ssh $_sshhost "cat - > \"$_rpath/$file\""
copy_and_print "$file"
return
fi
# hopefully never reached
echo "Unhandled situation for: $item"
) # leave scope & reset variables
done
fi
# USAGE
if [ $# -eq 0 ]
then
echo "usage: upload [command] [ext] [<files>]"
echo " upload [filename] < file"
echo " cat file | upload [filename]"
echo
echo " Commands:"
echo " rm <files> - remove files"
echo " rml - remove last upload"
echo " ls - list files"
echo " l|last - list last file"
echo " -0..N - list N last files"
echo " mv|ren <oldname> <newname> - rename file"
echo " mvl|renl <newname> - rename last uploaded file"
echo " fixl - fix permission of last uploaded file"
echo
echo " Extensions:"
echo " sh, ksh, txt, log - add extension to file"
echo " gz, tgz - uploads file as archive (tgz is always used for folders)"
echo
echo " <files> - files or directories to upload (needs to be the last argument)"
echo
echo "Special Case:"
echo " When data is piped to the script it expects only one"
echo " optional argument, which would be the target filename."
echo
exit 2
fi

View File

@@ -18,7 +18,7 @@ nature
essen essen
🍏🍎🍐🍊🍋🍌🍉🍇🍓🍈🍒🍑🍍🍅🍆🌽🍠🍞🍳🍗🍖 🍔🍟🍕🍝🍜🍲🍛🍣🍱🍤🍚🍧🍨🍦🍮🍭🍬🍫🍩🍪🌰 🍏🍎🍐🍊🍋🍌🍉🍇🍓🍈🍒🍑🍍🍅🍆🌽🍠🍞🍳🍗🍖 🍔🍟🍕🍝🍜🍲🍛🍣🍱🍤🍚🍧🍨🍦🍮🍭🍬🍫🍩🍪🌰
🍯🍼☕🍵🍶🍺🍻🍷🍸🍹🍴 🍯🍼☕🍵🍶🍺🍻🍷🍸🍹🍴🥂🍾
activity activity

1
.bin/xdg-open Symbolic link
View File

@@ -0,0 +1 @@
nnn.sh

View File

@@ -5,8 +5,21 @@ then
exit 2 exit 2
fi fi
mkdir -p "$HOME/ytdl/$1/" if [ ! -d "$HOME/ytdl/$1/" ]
ksh-update-completions & then
mkdir -p "$HOME/ytdl/$1/"
update-ksh-completions
. $HOME/.kshrc.autocomplete
fi
cd "$HOME/ytdl/$1/" cd "$HOME/ytdl/$1/"
yt-dlp --cookies-from-browser chromium "$2" shift
yt-dlp \
--print filename \
--cookies-from-browser firefox \
--user-agent "Mozilla/5.0 (X11; Linux x86_64; rv:142.0) Gecko/20100101 Firefox/142.0" \
--preset-alias mp4 \
--embed-metadata \
--embed-subs \
--restrict-filenames \
-o "%(channel&{} - |)s%(uploader&{} - |)s%(playlist|&{} - )s%(playlist_index&{} - |)s%(title)s.%(ext)s" \
"$@"

4
.config/gopass/config Normal file
View File

@@ -0,0 +1,4 @@
[mounts]
path = /home/sdk/.password-store
[audit]
concurrency = 1

View File

@@ -4,8 +4,8 @@
require "lfs" require "lfs"
local unique_instance = require "unique_instance" -- local unique_instance = require "unique_instance"
unique_instance.open_links_in_new_window = true -- unique_instance.open_links_in_new_window = true
-- Set the number of web processes to use. A value of 0 means 'no limit'. -- Set the number of web processes to use. A value of 0 means 'no limit'.
-- luakit.process_limit = 1 -- luakit.process_limit = 1
@@ -57,10 +57,10 @@ local binds = require "binds"
local settings = require "settings" local settings = require "settings"
local settings_chrome = require "settings_chrome" local settings_chrome = require "settings_chrome"
settings.window.home_page = "luakit://newtab" -- settings.window.home_page = "luakit://newtab"
-- settings.window.scroll_step = 20 -- settings.window.scroll_step = 600
settings.window.zoom_step = 0.2 settings.window.zoom_step = 0.2
settings.webview.zoom_level = 100 settings.webview.zoom_level = 90
settings.window.close_with_last_tab = true settings.window.close_with_last_tab = true
-- search engines -- search engines
@@ -79,19 +79,19 @@ settings.window.search_engines.default = settings.window.search_engines.ddg
-- local adblock_chrome = require "adblock_chrome" -- local adblock_chrome = require "adblock_chrome"
-- Enable Developer Tools -- Enable Developer Tools
-- local webinspector = require "webinspector" local webinspector = require "webinspector"
-- Add uzbl-like form filling -- Add uzbl-like form filling
-- local formfiller = require "formfiller" local formfiller = require "formfiller"
-- formfiller.extend({ formfiller.extend({
-- pass = function(s) return io.popen("pass " .. s):read() end pass = function(s) return io.popen("pass " .. s):read() end
-- }) })
-- Add proxy support & manager -- Add proxy support & manager
-- local proxy = require "proxy" local proxy = require "proxy"
-- Add quickmarks support & manager -- Add quickmarks support & manager
-- local quickmarks = require "quickmarks" local quickmarks = require "quickmarks"
-- Add session saving/loading support -- Add session saving/loading support
-- local session = require "session" -- local session = require "session"
@@ -100,20 +100,20 @@ settings.window.search_engines.default = settings.window.search_engines.ddg
local gopher = require "gopher" local gopher = require "gopher"
-- Delete website data -- Delete website data
-- local clear_data = require "clear_data" local clear_data = require "clear_data"
-- Add command to list closed tabs & bind to open closed tabs -- Add command to list closed tabs & bind to open closed tabs
local undoclose = require "undoclose" local undoclose = require "undoclose"
-- Add command to list tab history items -- Add command to list tab history items
-- local tabhistory = require "tabhistory" local tabhistory = require "tabhistory"
-- Add greasemonkey-like javascript userscript support -- Add greasemonkey-like javascript userscript support
--- local userscripts = require "userscripts" local userscripts = require "userscripts"
-- Add bookmarks support -- Add bookmarks support
-- local bookmarks = require "bookmarks" local bookmarks = require "bookmarks"
-- local bookmarks_chrome = require "bookmarks_chrome" local bookmarks_chrome = require "bookmarks_chrome"
-- Add download support -- Add download support
local downloads = require "downloads" local downloads = require "downloads"
@@ -121,7 +121,7 @@ local downloads_chrome = require "downloads_chrome"
downloads.default_dir = os.getenv("HOME") .. "/Downloads" downloads.default_dir = os.getenv("HOME") .. "/Downloads"
-- Add automatic PDF downloading and opening -- Add automatic PDF downloading and opening
local viewpdf = require "viewpdf" -- local viewpdf = require "viewpdf"
-- Add vimperator-like link hinting & following -- Add vimperator-like link hinting & following
local follow = require "follow" local follow = require "follow"
@@ -133,7 +133,7 @@ local cmdhist = require "cmdhist"
local search = require "search" local search = require "search"
-- Add ordering of new tabs -- Add ordering of new tabs
-- local taborder = require "taborder" local taborder = require "taborder"
-- Save web history -- Save web history
local history = require "history" local history = require "history"
@@ -149,14 +149,17 @@ local completion = require "completion"
-- Press Control-E while in insert mode to edit the contents of the currently -- Press Control-E while in insert mode to edit the contents of the currently
-- focused <textarea> or <input> element, using `xdg-open` -- focused <textarea> or <input> element, using `xdg-open`
-- local open_editor = require "open_editor" -- local open_editor = require "open_editor"
-- local editor = require "editor" local editor = require "editor"
-- editor.editor_cmd = "hterm vim {file}" editor.editor_cmd = "sterm vim {file}"
-- NoScript plugin, toggle scripts and or plugins on a per-domain basis. -- NoScript plugin, toggle scripts and or plugins on a per-domain basis.
-- `,ts` to toggle scripts, `,tp` to toggle plugins, `,tr` to reset. -- `,ts` to toggle scripts, `,tp` to toggle plugins, `,tr` to reset.
-- If you use this module, don't use any site-specific `enable_scripts` or -- If you use this module, don't use any site-specific `enable_scripts` or
-- `enable_plugins` settings, as these will conflict. -- `enable_plugins` settings, as these will conflict.
-- require "noscript" local noscript = require "noscript"
noscript.enable_scripts = false
noscript.enable_plugins = false
local follow_selected = require "follow_selected" local follow_selected = require "follow_selected"
local go_input = require "go_input" local go_input = require "go_input"
@@ -164,7 +167,7 @@ local go_next_prev = require "go_next_prev"
local go_up = require "go_up" local go_up = require "go_up"
-- Filter Referer HTTP header if page domain does not match Referer domain -- Filter Referer HTTP header if page domain does not match Referer domain
-- require_web_module("referer_control_wm") require_web_module("referer_control_wm")
local error_page = require "error_page" local error_page = require "error_page"
@@ -187,9 +190,9 @@ follow.stylesheet = follow.stylesheet .. [===[
-- local vertical_tabs = require "vertical_tabs" -- local vertical_tabs = require "vertical_tabs"
-- Add a stylesheet when showing images -- Add a stylesheet when showing images
-- local image_css = require "image_css" local image_css = require "image_css"
-- Add a new tab page -- -- Add a new tab page
local newtab_chrome = require "newtab_chrome" local newtab_chrome = require "newtab_chrome"
newtab_chrome.new_tab_src = [==[ newtab_chrome.new_tab_src = [==[
<html> <html>
@@ -207,7 +210,7 @@ local tab_favicons = require "tab_favicons"
-- tablist.min_width = 100 -- tablist.min_width = 100
-- Add :view-source command -- Add :view-source command
-- local view_source = require "view_source" local view_source = require "view_source"
-- Use "asdfqwerzxcv" for generating labels -- Use "asdfqwerzxcv" for generating labels
local select = require "select" local select = require "select"
@@ -217,75 +220,75 @@ end
follow.pattern_maker = follow.pattern_styles.match_label follow.pattern_maker = follow.pattern_styles.match_label
-- -- social media enhancer -- social media enhancer
-- local webview = require "webview" local webview = require "webview"
-- webview.add_signal('init', function (view) webview.add_signal('init', function (view)
-- view:add_signal('navigation-request', function(v, uri) view:add_signal('navigation-request', function(v, uri)
-- if v.uri:match('https://www.reddit.com') then if v.uri:match('https://www.reddit.com') then
-- v.uri = v.uri:gsub('%www.reddit.com', 'old.reddit.com') v.uri = v.uri:gsub('%www.reddit.com', 'old.reddit.com')
-- return true return true
-- end end
-- if v.uri:match('https://new.reddit.com') then if v.uri:match('https://new.reddit.com') then
-- v.uri = v.uri:gsub('%new.reddit.com', 'old.reddit.com') v.uri = v.uri:gsub('%new.reddit.com', 'old.reddit.com')
-- return true return true
-- end end
-- -- if v.uri:match('https://old.reddit.com') then if v.uri:match('https://old.reddit.com') then
-- -- v.uri = v.uri:gsub('%old.reddit.com', 'libreddit.kylrth.com') v.uri = v.uri:gsub('%old.reddit.com', 'redlib.kylrth.com')
-- -- return true return true
-- -- end end
-- -- if v.uri:match('https://old.reddit.com') then if v.uri:match('https://old.reddit.com') then
-- -- v.uri = v.uri:gsub('%old.reddit.com', 'libreddit.kylrth.com') v.uri = v.uri:gsub('%old.reddit.com', 'redlib.kylrth.com')
-- -- return true return true
-- -- end end
-- if v.uri:match('https://www.twitter.com') then if v.uri:match('https://www.twitter.com') then
-- v.uri = v.uri:gsub('%www.twitter.com', 'nitter.net') v.uri = v.uri:gsub('%www.twitter.com', 'nitter.net')
-- return true return true
-- end end
-- if v.uri:match('https://twitter.com') then if v.uri:match('https://twitter.com') then
-- v.uri = v.uri:gsub('%twitter.com', 'nitter.net') v.uri = v.uri:gsub('%twitter.com', 'nitter.net')
-- return true return true
-- end end
-- if v.uri:match('https://www.youtube.com') then if v.uri:match('https://www.youtube.com') then
-- v.uri = v.uri:gsub('%www.youtube.com', 'tube.cadence.moe') v.uri = v.uri:gsub('%www.youtube.com', 'tube.cadence.moe')
-- return true return true
-- end end
-- if v.uri:match('https://youtube.com') then if v.uri:match('https://youtube.com') then
-- v.uri = v.uri:gsub('%youtube.com', 'tube.cadence.moe') v.uri = v.uri:gsub('%youtube.com', 'tube.cadence.moe')
-- return true return true
-- end end
-- if v.uri:match('https://youtu.be') then if v.uri:match('https://youtu.be') then
-- v.uri = v.uri:gsub('%youtu.be/', 'tube.cadence.moe/watch?v=') v.uri = v.uri:gsub('%youtu.be/', 'tube.cadence.moe/watch?v=')
-- return true return true
-- end end
-- end) end)
-- end) end)
-- social media blocker -- social media blocker
-- local webview = require "webview" local webview = require "webview"
-- webview.add_signal('init', function (view) webview.add_signal('init', function (view)
-- view:add_signal('navigation-request', function(v, uri) view:add_signal('navigation-request', function(v, uri)
-- local blocklist_pattern = { local blocklist_pattern = {
-- "facebook.com", "facebook.com",
-- ".fb.com", ".fb.com",
-- ".fbcdn.com", ".fbcdn.com",
-- ".fbsbx.com", ".fbsbx.com",
-- ".fbcdn.net", ".fbcdn.net",
-- ".tfbnw.net", ".tfbnw.net",
-- "whatsapp.com", "whatsapp.com",
-- "online-metrix.net", "online-metrix.net",
-- ".fb.me", ".fb.me",
-- "facebook-web-clients.appspot.com", "facebook-web-clients.appspot.com",
-- "fbcdn-profile-a.akamaihd.net" "fbcdn-profile-a.akamaihd.net"
-- } }
-- for key,value in ipairs(blocklist_pattern) for key,value in ipairs(blocklist_pattern)
-- do do
-- if v.uri:match(value) then if v.uri:match(value) then
-- print("Navigation request to " .. v.uri .. " blocked.") print("Navigation request to " .. v.uri .. " blocked.")
-- return false return false
-- end end
-- end end
-- end) end)
-- end) end)
----------------------------- -----------------------------
-- End user script loading -- -- End user script loading --

View File

@@ -5,7 +5,7 @@
local theme = {} local theme = {}
-- Default settings -- Default settings
theme.font = "16px Terminess" theme.font = "20px IosevkaTerm"
theme.fg = "#D8D8D8" theme.fg = "#D8D8D8"
theme.bg = "#181818" theme.bg = "#181818"

View File

@@ -109,8 +109,8 @@ remove_set() {
while read file while read file
do do
case "$1" in case "$1" in
"Left") jpegtran -rotate 270 -outfile "$file" "$file" ;; "Right") jpegtran -rotate 270 -outfile "$file" "$file" ;;
"Right") jpegtran -rotate 90 -outfile "$file" "$file" ;; "Left") jpegtran -rotate 90 -outfile "$file" "$file" ;;
"c") copy_to_clipboard "$file" ;; "c") copy_to_clipboard "$file" ;;
"d") rm -f "$file" ;; "d") rm -f "$file" ;;
"e") edit_image "$file" ;; "e") edit_image "$file" ;;

View File

@@ -21,6 +21,7 @@ color_focus_free = rgb:AF/5F/00
color_unfocus = rgb:44/44/44 color_unfocus = rgb:44/44/44
color_unfocus_free = rgb:55/35/00 color_unfocus_free = rgb:55/35/00
disable_border = 0 disable_border = 0
disable_padding = 1
maximize_hide_bar = 0 maximize_hide_bar = 0
# +-------------------------------------------------- # +--------------------------------------------------
@@ -68,7 +69,7 @@ bar_at_bottom = 0
# ++ A literal + # ++ A literal +
# +@ Prefix for text markup sequences # +@ Prefix for text markup sequences
bar_format = +S +@bg=2;+L+@bg=0; +W +|R +A bar_format = +S +@bg=2;+L+@bg=0; i:+M +W +|R +A
# +-------------------------------------------------- # +--------------------------------------------------
# | WORKSPACE LAYOUT # | WORKSPACE LAYOUT
@@ -216,6 +217,7 @@ bind[bar_toggle_ws] = MOD+Shift+b
# LAYOUT # LAYOUT
bind[cycle_layout] = MOD+l bind[cycle_layout] = MOD+l
bind[flip_layout] = MOD+Shift+l bind[flip_layout] = MOD+Shift+l
bind[center_layout] = MOD+Shift+c
bind[float_toggle] = MOD+space bind[float_toggle] = MOD+space
bind[free_toggle] = MOD+Shift+space bind[free_toggle] = MOD+Shift+space

View File

@@ -4,7 +4,11 @@ indent=30
tabs=None tabs=None
linespacing=3 linespacing=3
wrapped-lines-linespacing=0 wrapped-lines-linespacing=0
<<<<<<< Updated upstream
font=FuraCode Nerd Font Mono weight=450 14 font=FuraCode Nerd Font Mono weight=450 14
=======
font=.AppleSystemUIFont 17
>>>>>>> Stashed changes
justify= justify=
background=#cccccc background=#cccccc
@@ -32,7 +36,6 @@ wrap-mode=GTK_WRAP_NONE
indent=20 indent=20
[Tag link] [Tag link]
foreground=#8cd3ff
[Tag tag] [Tag tag]
foreground=#ce5c00 foreground=#ce5c00

View File

@@ -1 +1,4 @@
set startup-quietly on set startup-quietly on
set follow-fork-mode parent
set detach-on-fork off
set schedule-multiple on

View File

@@ -6,7 +6,7 @@ python
# License ---------------------------------------------------------------------- # License ----------------------------------------------------------------------
# Copyright (c) 2015-2023 Andrea Cardaci <cyrus.and@gmail.com> # Copyright (c) 2015-2024 Andrea Cardaci <cyrus.and@gmail.com>
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal # of this software and associated documentation files (the "Software"), to deal
@@ -346,7 +346,7 @@ def fetch_breakpoints(watchpoints=False, pending=False):
parsed_breakpoints[number] = [address_info], is_pending, '' parsed_breakpoints[number] = [address_info], is_pending, ''
elif len(fields) >= 5 and fields[1] == 'catchpoint': elif len(fields) >= 5 and fields[1] == 'catchpoint':
# only take before comma, but ignore commas in quotes # only take before comma, but ignore commas in quotes
what = catch_what_regex.search(' '.join(fields[4:]))[0].strip() what = catch_what_regex.search(' '.join(fields[4:])).group(0).strip()
parsed_breakpoints[number] = [], False, what parsed_breakpoints[number] = [], False, what
elif len(fields) >= 3 and number in parsed_breakpoints: elif len(fields) >= 3 and number in parsed_breakpoints:
# add this address to the list of multiple locations # add this address to the list of multiple locations

View File

@@ -18,8 +18,8 @@
name = Stefan Hagen name = Stefan Hagen
email = sh+github@codevoid.de email = sh+github@codevoid.de
[user] [user]
name = c0dev0id name = Stefan Hagen
email = sh+git@codevoid.de email = stefan.hagen@sap.com
[hub] [hub]
host = github.wdf.sap.corp host = github.wdf.sap.corp
protocol = git protocol = git
@@ -39,3 +39,15 @@
[credential "https://github.wdf.sap.corp"] [credential "https://github.wdf.sap.corp"]
helper = helper =
helper = !/usr/bin/gh auth git-credential helper = !/usr/bin/gh auth git-credential
[difftool]
prompt = false
[filter "lfs"]
clean = git-lfs clean -- %f
smudge = git-lfs smudge -- %f
process = git-lfs filter-process
required = true
[credential]
helper =
helper = /usr/local/share/gcm-core/git-credential-manager
[credential "https://dev.azure.com"]
useHttpPath = true

124
.kshrc
View File

@@ -27,7 +27,7 @@ export LANG LC_MESSAGES LC_NUMERIC LC_TIME
### SOFTWARE PREFERENCES ### SOFTWARE PREFERENCES
EDITOR="vim" EDITOR="vim"
VISUAL="vim" VISUAL="vim"
BROWSER="chrome" BROWSER="firefox"
PAGER="less" PAGER="less"
export EDITOR VISUAL BROWSER PAGER export EDITOR VISUAL BROWSER PAGER
@@ -86,8 +86,8 @@ TOG_COLORS=1
export GOT_AUTHOR TOG_COLORS export GOT_AUTHOR TOG_COLORS
# BUPSTASH # BUPSTASH
BUPSTASH_REPOSITORY=ssh://sdk@storage.bupstash.io BUPSTASH_REPOSITORY=ssh://default@storage.bupstash.io
BUPSTASH_KEY_COMMAND="pass Internet/bupstash-key" BUPSTASH_KEY_COMMAND="pass Internet/storage.bupstash.io-key"
export BUPSTASH_REPOSITORY BUPSTASH_KEY_COMMAND export BUPSTASH_REPOSITORY BUPSTASH_KEY_COMMAND
# PASSWORD-STORE # PASSWORD-STORE
@@ -107,7 +107,7 @@ set bell-style none
# LOAD COMPLETION FILE # LOAD COMPLETION FILE
######################################################################## ########################################################################
[ -f ~/.ksh.complete ] && . ~/.ksh.complete [ -f ~/.kshrc.autocomplete ] && . ~/.kshrc.autocomplete
######################################################################## ########################################################################
# PROMPT # PROMPT
@@ -127,11 +127,26 @@ RED="\[$(tput setaf 196)\]"
GREY="\[$(tput setaf 248)\]" GREY="\[$(tput setaf 248)\]"
RESET="\[$(tput op)\]" RESET="\[$(tput op)\]"
gitstatus() {
_path="$PWD"
while [ -n "$_path" ]
do [ -d "$_path/.git" ] \
&& echo "($(git --no-pager branch --no-color --show-current))" \
&& break
_path="${_path%/*}"
done
}
if [ $(id -u) -eq 0 ] if [ $(id -u) -eq 0 ]
then then
PS1="${x}${RED}\${?}|\w\\$ ${RESET}${x}" PS1="${x}${RED}$(hostname -s) \${?}|\w\\$ ${RESET}${x}"
else else
PS1="${x}${GREY}\${?}|\w\\$ ${RESET}${x}" if command -v git > /dev/null
then
PS1="${x}${GREY}$(hostname -s) \${?}|\w\$(gitstatus)\\$ ${RESET}${x}"
else
PS1="${x}${GREY}$(hostname -s) \${?}|\w\\$ ${RESET}${x}"
fi
fi fi
######################################################################## ########################################################################
@@ -147,19 +162,28 @@ alias luakitrc="vim ~/.config/luakit/rc.lua"
alias spectrwmrc="vim ~/.config/spectrwm/spectrwm.conf" alias spectrwmrc="vim ~/.config/spectrwm/spectrwm.conf"
alias vifmrc="vim ~/.config/vifm/vifmrc" alias vifmrc="vim ~/.config/vifm/vifmrc"
alias tmuxrc="vim ~/.tmux.conf" alias tmuxrc="vim ~/.tmux.conf"
alias annex="git annex"
pastebinvim() {
vim "https://pastebin.com/raw/$(basename "$1")";
}
# task warrior # task warrior
alias t=task #alias t=task
alias ta="t add" #alias ta="t add"
alias tm="t mod" #alias tm="t mod"
alias tc="t completed" #alias tc="t completed"
alias tlog="t log +LOG" #alias tlog="t log +LOG"
alias mc="/usr/local/bin/mc -d"
# social media # social media
alias tuta="tut -u 'sh@bsd.network uugrn@chaos.social'" alias tuta="tut -u 'sh@bsd.network uugrn@chaos.social'"
# servers # servers
alias x="ssh -t sdk@home.codevoid.de 'tmux -u new-session -d -s main; tmux -u new-session -t main \; set-option destroy-unattached'" alias x="ssh -t sdk@home.codevoid.de \
'tmux -u new-session -d -s main; \
tmux -u new-session -t main \; \
set-option destroy-unattached'"
alias inssh="ssh -o HostKeyAlgorithms=+ssh-rsa \ alias inssh="ssh -o HostKeyAlgorithms=+ssh-rsa \
-o KexAlgorithms=+diffie-hellman-group1-sha1 \ -o KexAlgorithms=+diffie-hellman-group1-sha1 \
@@ -168,11 +192,71 @@ alias inssh="ssh -o HostKeyAlgorithms=+ssh-rsa \
myps() { ps -fU $(whoami); } myps() { ps -fU $(whoami); }
mytop() { top -u $(whoami); } mytop() { top -u $(whoami); }
alias pkg-readmes="cd /usr/local/share/doc/pkg-readmes; ls"
alias notes="cd $HOME/Documents/notes; nnn"
# git
alias mygit-commit="git commit"
alias mygit-rebase="git rebase -i"
alias mygit-stage="git add"
alias mygit-unstage="git restore --staged"
alias mygit-untrack="git rm --cached"
alias mygit-track="git add --intent-to-add"
alias mygit-update="git fetch --all"
alias mygit-diff="git difftool -y ..origin/HEAD"
alias mygit-log="git log --graph"
alias mygit-list-branches="git --no-pager branch --all"
alias mygit-delete-branch="git branch -D"
mygit-upstream-sync() {
if [ -z "$1" ]
then
echo "sync with which upstream branch?"
return
fi
set -xe
git fetch upstream
git checkout $1
git merge upstream/$1
git push origin $1
}
mygit-checkout() {
_local="$(echo "$1" | sed 's,remotes/,,g;s,origin/,,g;')"
git checkout -b $_local $1
}
alias mygit-changed-files="git --no-pager whatchanged origin/HEAD..HEAD | grep -E '^:' | awk '{ print \$6; }'"
mygot-clone() {
if test -z "$1" || test -z "$2"
then echo "mygot clone <url> <dir>"
else
_src="${1%*.git}.git"
_dst="${2%*.git}"
got clone "$_src" "$_dst.git"
got checkout "$_dst.git" "$_dst"
cd "$_dst"
fi
}
# other # other
alias portroach="portroach-cli -m codevoid" alias portroach="portroach-cli -m codevoid"
alias ugrep="\ugrep -nI --exclude=tags --exclude=.tags --exclude='cscope.*'" alias ugrep="\ugrep -nI --exclude=tags --exclude=.tags --exclude='cscope.*'"
alias joplin="firefox https://app.joplincloud.com &" alias tarsnap="doas \tarsnap"
alias vpn-on="doas wg-quick up wg0"
alias vpn-off="doas wg-quick down wg0"
alias edit-pf="doas vim /etc/pf.conf && doas pfctl -f /etc/pf.conf"
alias edit-wg="doas vim /etc/hostname.wg0 && doas sh /etc/netstart wg0"
alias log-wg="doas ifconfig wg0 debug; doas tail -f /var/log/messages | grep wg0"
alias log-wg-remote="ssh shell.codevoid.de 'doas ifconfig wg0 debug; doas tail -f /var/log/messages | grep wg0'"
mystuff() {
cd /usr/ports/mystuff
g
}
wip() {
cd /usr/ports/openbsd-wip
g
}
######################################################################## ########################################################################
# AMUSED # AMUSED
@@ -293,8 +377,8 @@ obsd-full-system-update() {(
# REMIND # REMIND
######################################################################## ########################################################################
alias rem="remind -@1,1,1 -c+cu4 -wt ~sdk/.reminders.rem" alias rem="remind -@1,1,1 -c+cu4 -wt -m ~sdk/.reminders.rem"
alias remy="remind -@1,1,1 -c+cu52 -wt ~sdk/.reminders.rem | less" alias remy="remind -@1,1,1 -c+cu52 -wt -m ~sdk/.reminders.rem | less"
alias rems="remind -n ~sdk/.reminders | sort -n | head -10" alias rems="remind -n ~sdk/.reminders | sort -n | head -10"
alias remc="remindcal ~sdk/.reminders" alias remc="remindcal ~sdk/.reminders"
alias rem-personal="rem-edit personal" alias rem-personal="rem-edit personal"
@@ -306,11 +390,13 @@ rem-edit() {
scp -q sdk@home.codevoid.de:.reminders/$1.rem ~sdk/.reminders/$1.rem scp -q sdk@home.codevoid.de:.reminders/$1.rem ~sdk/.reminders/$1.rem
} }
rem-edit-uugrn() { rem-edit-uugrn() {
vim sftp://vorstand@vorstand.uugrn.org/.reminders/uugrn.rem # edit remote file
scp -q vorstand@vorstand.uugrn.org:.reminders/uugrn.rem ~sdk/.reminders/uugrn.rem vim sftp://vorstand@vorstand.uugrn.org/private/Kalender/uugrn.rem
scp -q ~sdk/.reminders/uugrn.rem vorstand@vorstand.uugrn.org:private/Kalender/uugrn.rem # update local file
scp -q sdk@vorstand.uugrn.org:~vorstand/private/Kalender/uugrn.rem ~sdk/.reminders/uugrn.rem
# run update script
ssh sdk@vorstand.uugrn.org sh \ ssh sdk@vorstand.uugrn.org sh \
~sdk/.bin/make_calendar.sh \ ~vorstand/private/Kalender/scripts/make_calendar.sh \
|| true || true
} }

View File

@@ -1,46 +0,0 @@
@-moz-document domain(old.reddit.com) {
* {
background-color: #181818 !important;
color: #CCC !important;
border-color: #555 !important;
border-width: 0px !important;
}
.premium-banner-outer, .premium-banner {
display: none !important;
}
#header-img.default-header, .side {
display: none !important;
}
.link.promotedlink.promoted, .link.promotedlink.external {
display: none !important;
}
.footer-parent {
display: none !important;
}
.happening-now-wrap {
display: none !important;
}
.stickied {
display: none !important;
}
input, textarea, button {
background-color: #282828 !important;
}
a {
font-style: oblique !important;
}
.expando-button, .thumbnail, .rank, .midcol {
display: none !important;
}
.top-matter, .top-matter > *, .top-matter > * > *, .top-matter > * > * > *, .top-matter > * > * > * > * {
background-color: #222 !important;
}
.linkflairlabel, .linkflairlabel > * {
background-color: #999 !important;
color: #121212 !important;
}
.entry {
border-left: 5px solid darkred !important;
padding-left: 5px !important;
}
}

View File

@@ -33,3 +33,5 @@ color body green default "^\\+"
color body green default "^\\+.*" color body green default "^\\+.*"
color body green default "> \\+.*" color body green default "> \\+.*"
color index red default '~F' # flagged
color index green default '@~f .' # aliased

View File

@@ -27,7 +27,7 @@ text/html; w3m -I %{charset} -T %t -cols "$COLUMNS" -s -no-graph -o display_link
message/*; cat %s; needsterminal; message/*; cat %s; needsterminal;
# documents # documents
application/pdf; ~/.mutt/scripts/call.sh mupdf %s; nametemplate=%s.pdf; application/pdf; ~/.mutt/scripts/call.sh zathura %s; nametemplate=%s.pdf;
application/vnd.openxmlformats-officedocument.wordprocessingml.document; ~/.mutt/scripts/call.sh libreoffice %s; application/vnd.openxmlformats-officedocument.wordprocessingml.document; ~/.mutt/scripts/call.sh libreoffice %s;
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; ~/.mutt/scripts/call.sh libreoffice %s; application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; ~/.mutt/scripts/call.sh libreoffice %s;
application/vnd.openxmlformats-officedocument.presentationml.presentation; ~/.mutt/scripts/call.sh libreoffice %s; application/vnd.openxmlformats-officedocument.presentationml.presentation; ~/.mutt/scripts/call.sh libreoffice %s;

View File

@@ -211,18 +211,16 @@ unalternative_order *
alternative_order text/plain text/enriched text/html alternative_order text/plain text/enriched text/html
auto_view text/html text/enriched text/calendar auto_view text/html text/enriched text/calendar
# Preview HTML # apply inline patch
macro pager,attach \cs "<pipe-message>cat > /tmp/muttpatch.diff<enter><shell-escape>~/.mutt/scripts/portpatch2.sh /tmp/muttpatch.diff<enter>" macro index,pager,attach \cs "| ~/.mutt/scripts/patch.sh patch<enter>"
macro index,pager,attach \ca "| ~/.mutt/scripts/patch.sh git<enter>"
# Save Patch
#macro pager \cs "<shell-escape>rm -f /tmp/mutt-patch.diff<enter><copy-message>/tmp/mutt-patch.diff<enter><enter-command>echo 'Saved as /tmp/mutt-patch.diff'<enter><shell-escape>~/.mutt/scripts/portpatch.sh /tmp/mutt-patch.diff<enter>"
# pipe-message # pipe-message
set pipe_decode_weed = no set pipe_decode_weed = no
set pipe_decode = yes # when piping via pipe-message command, strip headers and decode set pipe_decode = yes # when piping via pipe-message command, strip headers and decode
set pipe_split = yes # if several msgs are tagged, do the pipe-message command for each set pipe_split = yes # if several msgs are tagged, do the pipe-message command for each
set prompt_after = no # promt if external pager exits set prompt_after = no # promt if external pager exits
set wait_key = no # wait for a key-press after performing shell/external commands set wait_key = yes # wait for a key-press after performing shell/external commands
set beep_new = no # beep if new message arrives set beep_new = no # beep if new message arrives
set check_new = no # check for new mails, while the mailbox is open set check_new = no # check for new mails, while the mailbox is open
set auto_tag = yes # function will applied to all tagged messages in the index set auto_tag = yes # function will applied to all tagged messages in the index
@@ -321,4 +319,9 @@ set crypt_opportunistic_encrypt_strong_keys = yes # autoselect key with trust fu
set autocrypt = no set autocrypt = no
set pgp_use_gpg_agent = yes set pgp_use_gpg_agent = yes
set alias_file=~/.mutt/aliases
set sort_alias = alias
set reverse_alias = yes
source ~/.mutt/aliases
source ~/.mutt/colors/codevoid source ~/.mutt/colors/codevoid

View File

@@ -1,20 +0,0 @@
#!/bin/sh
strip=0
clear
printf '\n---------------------------------------------------------------------\n'
egrep '^Index|^RCS|^diff --git|^file +' "$1" | sed 's,/cvs,/usr,g'
printf '---------------------------------------------------------------------\n\n'
printf "Path for patch [/usr/ports]? "
read _path
[ -z "$_path" ] && _path=/usr/ports
egrep -q '^diff --git a/' "$1" && strip=1
#print "Trying to apply patch"
#qprint -d "$1" "$1.out"
doas patch -Ep"$strip" -d $_path < "$1"
cd $_path && ksh

68
.mutt/scripts/patch.sh Executable file
View File

@@ -0,0 +1,68 @@
#!/bin/ksh -e
# needs converters/qprint
if [ -t 0 ] || [ -z "$1" ]
then
echo "usage: patch.sh [git|patch] < patchfile.diff"
exit 2
fi
echo "Shortcuts:"
echo "ld - luakit-dev"
echo "lt - luakit-test"
echo "ltmp - luakit-tmp"
echo "src - /usr/src"
echo "sys - /usr/src/sys"
echo "ports - /usr/ports"
echo "www - /usr/www"
echo
printf "Path [$PWD]: "
read _reply < /dev/tty
if [ -z "$_reply" ]
then
_path="$PWD"
else
_path="$_reply"
fi
# shortcuts!!!
case "$_path" in
ld) _path="/home/sdk/src/luakit-dev" ;;
lt) _path="/home/sdk/src/luakit-test" ;;
ltmp) _path="/home/sdk/src/luakit-tmp" ;;
src) _path="/usr/src" ;;
sys) _path="/usr/src/sys" ;;
ports) _path="/usr/ports" ;;
esac
if [ ! -d "$_path" ]
then
_path="$(port-jump "$_path")"
fi
print "Using: $_path"
if [ ! -d "$_path" ]
then
echo "Error with path: $_path"
exit 2
fi
cd "$_path"
if [ "$1" == "git" ]
then
cat /dev/stdin | git am
fi
if [ "$1" == "patch" ]
then
printf "Strip [0]: "
read _strip < /dev/tty
_strip=${_strip:=0}
cat /dev/stdin | doas -u sdk patch -E -N -p$_strip -d "$_path"
fi
echo "$_path" | xclip

View File

@@ -1,35 +0,0 @@
#!/bin/ksh -e
# needs converters/qprint
# mutt: macro pager,attach \cs "<pipe-message>cat > /tmp/muttpatch.diff<enter><shell-escape>~/.mutt/scripts/portpatch2.sh /tmp/muttpatch.diff<enter>"
clear
printf '\n---------------------------------------------------------------------\n'
grep -E 'Subject: |^Index|^RCS|^diff --git|^file +|^[-+]{3} ' "${1}"
printf '---------------------------------------------------------------------\n\n'
printf "Base path for the patch?\n"
printf "Example: /usr/ports or /usr/src\n"
printf ": "
read -r _path
cd $_path
print "Using: $_path"
printf "Fix quoted-printable mangeled patch? [y/N]: "
read -r _qprint
case ${_qprint} in
[y|Y]) _catcmd="qprint -d"; ;;
*) _catcmd="cat"; ;;
esac
printf "Strip? [0]: "
read -r _strip
echo "CMD: ${_catcmd} "${1}" | doas -u sdk patch -E -pp${_strip:=0} -d ${_path}"
${_catcmd} "${1}" | doas -u sdk patch -i -E -N -p${_strip:=0} -d ${_path}
echo ${_path} | xclip
echo "done.
read

View File

@@ -53,6 +53,10 @@ Host home.codevoid.de
Hostname home.codevoid.de Hostname home.codevoid.de
User sdk User sdk
Host backup-fsn.codevoid.de
User u475462-sub1
Port 23
Host dalek Host dalek
Hostname dalek.home.codevoid.de Hostname dalek.home.codevoid.de
User sdk User sdk

35
.vim/bin/findtagsdir Executable file
View File

@@ -0,0 +1,35 @@
#!/bin/sh
gitdir() {
_path="$PWD"
while [ -n "$_path" ]
do [ -d "$_path/.git" ] \
&& echo "$_path" \
&& break
_path="${_path%/*}"
done
}
cvsdir() {
_path="$PWD"
while [ -n "$_path" ]
do
[ ! -d "$_path/../CVS" ] \
&& echo "$_path" \
&& break
_path="${_path%/*}"
done
}
_gitdir="$(gitdir)"
_cvsdir="$(cvsdir)"
if [ -n "$_gitdir" ]
then
echo "$_gitdir/.git"
elif [ -n "$_cvsdir" ]
then
echo "$_cvsdir/.tags"
else
echo "$PWD/.tags"
fi

View File

@@ -1,4 +0,0 @@
GitHub Copilot is offered under the [GitHub Terms of
Service](https://docs.github.com/en/site-policy/github-terms/github-terms-for-additional-products-and-features#github-copilot).
Copyright (C) 2023 GitHub, Inc. - All Rights Reserved.

View File

@@ -1,64 +0,0 @@
# GitHub Copilot for Vim and Neovim
GitHub Copilot uses OpenAI Codex to suggest code and entire functions in
real-time right from your editor. Trained on billions of lines of public
code, GitHub Copilot turns natural language prompts including comments and
method names into coding suggestions across dozens of languages.
Copilot.vim is a Vim/Neovim plugin for GitHub Copilot.
To learn more, visit
[https://github.com/features/copilot](https://github.com/features/copilot).
## Subscription
GitHub Copilot requires a subscription. It is free for verified students and
maintainers of popular open source projects on GitHub.
GitHub Copilot is subject to the [GitHub Additional Product
Terms](https://docs.github.com/en/site-policy/github-terms/github-terms-for-additional-products-and-features).
## Getting started
1. Install [Neovim][] or the latest patch of [Vim][] (9.0.0185 or newer).
2. Install [Node.js][].
3. Install `github/copilot.vim` using vim-plug, packer.nvim, or any other
plugin manager. Or to install manually, run one of the following
commands:
* Vim, Linux/macOS:
git clone https://github.com/github/copilot.vim.git \
~/.vim/pack/github/start/copilot.vim
* Neovim, Linux/macOS:
git clone https://github.com/github/copilot.vim.git \
~/.config/nvim/pack/github/start/copilot.vim
* Vim, Windows (PowerShell command):
git clone https://github.com/github/copilot.vim.git `
$HOME/vimfiles/pack/github/start/copilot.vim
* Neovim, Windows (PowerShell command):
git clone https://github.com/github/copilot.vim.git `
$HOME/AppData/Local/nvim/pack/github/start/copilot.vim
4. Start Vim/Neovim and invoke `:Copilot setup`.
[Node.js]: https://nodejs.org/en/download/
[Neovim]: https://github.com/neovim/neovim/releases/latest
[Vim]: https://github.com/vim/vim
Suggestions are displayed inline and can be accepted by pressing the tab key.
See `:help copilot` for more information.
## Troubleshooting
Wed love to get your help in making GitHub Copilot better! If you have
feedback or encounter any problems, please reach out on our [Feedback
forum](https://github.com/orgs/community/discussions/categories/copilot).

View File

@@ -1,4 +0,0 @@
If you discover a security issue in this repo, please submit it through the
[GitHub Security Bug Bounty](https://hackerone.com/github).
Thanks for helping make GitHub Copilot safe for everyone.

View File

@@ -1,860 +0,0 @@
scriptencoding utf-8
let s:has_nvim_ghost_text = has('nvim-0.7') && exists('*nvim_buf_get_mark')
let s:vim_minimum_version = '9.0.0185'
let s:has_vim_ghost_text = has('patch-' . s:vim_minimum_version) && has('textprop')
let s:has_ghost_text = s:has_nvim_ghost_text || s:has_vim_ghost_text
let s:hlgroup = 'CopilotSuggestion'
let s:annot_hlgroup = 'CopilotAnnotation'
if s:has_vim_ghost_text && empty(prop_type_get(s:hlgroup))
call prop_type_add(s:hlgroup, {'highlight': s:hlgroup})
endif
if s:has_vim_ghost_text && empty(prop_type_get(s:annot_hlgroup))
call prop_type_add(s:annot_hlgroup, {'highlight': s:annot_hlgroup})
endif
function! s:Echo(msg) abort
if has('nvim') && &cmdheight == 0
call v:lua.vim.notify(a:msg, v:null, {'title': 'GitHub Copilot'})
else
echo a:msg
endif
endfunction
function! s:EditorConfiguration() abort
let filetypes = copy(s:filetype_defaults)
if type(get(g:, 'copilot_filetypes')) == v:t_dict
call extend(filetypes, g:copilot_filetypes)
endif
return {
\ 'enableAutoCompletions': empty(get(g:, 'copilot_enabled', 1)) ? v:false : v:true,
\ 'disabledLanguages': map(sort(keys(filter(filetypes, { k, v -> empty(v) }))), { _, v -> {'languageId': v}}),
\ }
endfunction
function! copilot#Init(...) abort
call copilot#util#Defer({ -> exists('s:client') || s:Start() })
endfunction
function! s:Running() abort
return exists('s:client.job') || exists('s:client.client_id')
endfunction
function! s:Start() abort
if s:Running() || exists('s:client.startup_error')
return
endif
let s:client = copilot#client#New({'editorConfiguration' : s:EditorConfiguration()})
endfunction
function! s:Stop() abort
if exists('s:client')
let client = remove(s:, 'client')
call client.Close()
endif
endfunction
function! copilot#Client() abort
call s:Start()
return s:client
endfunction
function! copilot#RunningClient() abort
if s:Running()
return s:client
else
return v:null
endif
endfunction
if has('nvim-0.7') && !has(luaeval('vim.version().api_prerelease') ? 'nvim-0.8.1' : 'nvim-0.8.0')
let s:editor_warning = 'Neovim 0.7 support is deprecated and will be dropped in a future release of copilot.vim.'
endif
if has('vim_starting') && exists('s:editor_warning')
call copilot#logger#Warn(s:editor_warning)
endif
function! s:EditorVersionWarning() abort
if exists('s:editor_warning')
echohl WarningMsg
echo 'Warning: ' . s:editor_warning
echohl None
endif
endfunction
function! copilot#Request(method, params, ...) abort
let client = copilot#Client()
return call(client.Request, [a:method, a:params] + a:000)
endfunction
function! copilot#Call(method, params, ...) abort
let client = copilot#Client()
return call(client.Call, [a:method, a:params] + a:000)
endfunction
function! copilot#Notify(method, params, ...) abort
let client = copilot#Client()
return call(client.Notify, [a:method, a:params] + a:000)
endfunction
function! copilot#NvimNs() abort
return nvim_create_namespace('github-copilot')
endfunction
function! copilot#Clear() abort
if exists('g:_copilot_timer')
call timer_stop(remove(g:, '_copilot_timer'))
endif
if exists('b:_copilot')
call copilot#client#Cancel(get(b:_copilot, 'first', {}))
call copilot#client#Cancel(get(b:_copilot, 'cycling', {}))
endif
call s:UpdatePreview()
unlet! b:_copilot
return ''
endfunction
function! copilot#Dismiss() abort
call copilot#Clear()
call s:UpdatePreview()
return ''
endfunction
let s:filetype_defaults = {
\ 'gitcommit': 0,
\ 'gitrebase': 0,
\ 'hgcommit': 0,
\ 'svn': 0,
\ 'cvs': 0,
\ '.': 0}
function! s:BufferDisabled() abort
if &buftype =~# '^\%(help\|prompt\|quickfix\|terminal\)$'
return 5
endif
if exists('b:copilot_disabled')
return empty(b:copilot_disabled) ? 0 : 3
endif
if exists('b:copilot_enabled')
return empty(b:copilot_enabled) ? 4 : 0
endif
let short = empty(&l:filetype) ? '.' : split(&l:filetype, '\.', 1)[0]
let config = {}
if type(get(g:, 'copilot_filetypes')) == v:t_dict
let config = g:copilot_filetypes
endif
if has_key(config, &l:filetype)
return empty(config[&l:filetype])
elseif has_key(config, short)
return empty(config[short])
elseif has_key(config, '*')
return empty(config['*'])
else
return get(s:filetype_defaults, short, 1) == 0 ? 2 : 0
endif
endfunction
function! copilot#Enabled() abort
return get(g:, 'copilot_enabled', 1)
\ && empty(s:BufferDisabled())
endfunction
let s:inline_invoked = 1
let s:inline_automatic = 2
function! copilot#Complete(...) abort
if exists('g:_copilot_timer')
call timer_stop(remove(g:, '_copilot_timer'))
endif
let target = [bufnr(''), getbufvar('', 'changedtick'), line('.'), col('.')]
if !exists('b:_copilot.target') || b:_copilot.target !=# target
if exists('b:_copilot.first')
call copilot#client#Cancel(b:_copilot.first)
endif
if exists('b:_copilot.cycling')
call copilot#client#Cancel(b:_copilot.cycling)
endif
let params = {
\ 'textDocument': {'uri': bufnr('')},
\ 'position': copilot#util#AppendPosition(),
\ 'formattingOptions': {'insertSpaces': &expandtab ? v:true : v:false, 'tabSize': shiftwidth()},
\ 'context': {'triggerKind': s:inline_automatic}}
let b:_copilot = {
\ 'target': target,
\ 'params': params,
\ 'first': copilot#Request('textDocument/inlineCompletion', params)}
let g:_copilot_last = b:_copilot
endif
let completion = b:_copilot.first
if !a:0
return completion.Await()
else
call copilot#client#Result(completion, function(a:1, [b:_copilot]))
if a:0 > 1
call copilot#client#Error(completion, function(a:2, [b:_copilot]))
endif
endif
endfunction
function! s:HideDuringCompletion() abort
return get(g:, 'copilot_hide_during_completion', 1)
endfunction
function! s:SuggestionTextWithAdjustments() abort
let empty = ['', 0, 0, {}]
try
if mode() !~# '^[iR]' || (s:HideDuringCompletion() && pumvisible()) || !exists('b:_copilot.suggestions')
return empty
endif
let choice = get(b:_copilot.suggestions, b:_copilot.choice, {})
if !has_key(choice, 'range') || choice.range.start.line != line('.') - 1 || type(choice.insertText) !=# v:t_string
return empty
endif
let line = getline('.')
let offset = col('.') - 1
let choice_text = strpart(line, 0, copilot#util#UTF16ToByteIdx(line, choice.range.start.character)) . substitute(choice.insertText, "\n*$", '', '')
let typed = strpart(line, 0, offset)
let end_offset = copilot#util#UTF16ToByteIdx(line, choice.range.end.character)
if end_offset < 0
let end_offset = len(line)
endif
let delete = strpart(line, offset, end_offset - offset)
if typed =~# '^\s*$'
let leading = matchstr(choice_text, '^\s\+')
let unindented = strpart(choice_text, len(leading))
if strpart(typed, 0, len(leading)) == leading && unindented !=# delete
return [unindented, len(typed) - len(leading), strchars(delete), choice]
endif
elseif typed ==# strpart(choice_text, 0, offset)
return [strpart(choice_text, offset), 0, strchars(delete), choice]
endif
catch
call copilot#logger#Exception()
endtry
return empty
endfunction
function! s:Advance(count, context, ...) abort
if a:context isnot# get(b:, '_copilot', {})
return
endif
let a:context.choice += a:count
if a:context.choice < 0
let a:context.choice += len(a:context.suggestions)
endif
let a:context.choice %= len(a:context.suggestions)
call s:UpdatePreview()
endfunction
function! s:GetSuggestionsCyclingCallback(context, result) abort
let callbacks = remove(a:context, 'cycling_callbacks')
let seen = {}
for suggestion in a:context.suggestions
let seen[suggestion.insertText] = 1
endfor
for suggestion in get(a:result, 'items', [])
if !has_key(seen, suggestion.insertText)
call add(a:context.suggestions, suggestion)
let seen[suggestion.insertText] = 1
endif
endfor
for Callback in callbacks
call Callback(a:context)
endfor
endfunction
function! s:GetSuggestionsCycling(callback) abort
if exists('b:_copilot.cycling_callbacks')
call add(b:_copilot.cycling_callbacks, a:callback)
elseif exists('b:_copilot.cycling')
call a:callback(b:_copilot)
elseif exists('b:_copilot.suggestions')
let params = deepcopy(b:_copilot.first.params)
let params.context.triggerKind = s:inline_invoked
let b:_copilot.cycling_callbacks = [a:callback]
let b:_copilot.cycling = copilot#Request('textDocument/inlineCompletion',
\ params,
\ function('s:GetSuggestionsCyclingCallback', [b:_copilot]),
\ function('s:GetSuggestionsCyclingCallback', [b:_copilot]),
\ )
call s:UpdatePreview()
endif
return ''
endfunction
function! copilot#Next() abort
return s:GetSuggestionsCycling(function('s:Advance', [1]))
endfunction
function! copilot#Previous() abort
return s:GetSuggestionsCycling(function('s:Advance', [-1]))
endfunction
function! copilot#GetDisplayedSuggestion() abort
let [text, outdent, delete, item] = s:SuggestionTextWithAdjustments()
return {
\ 'item': item,
\ 'text': text,
\ 'outdentSize': outdent,
\ 'deleteSize': delete}
endfunction
function! s:ClearPreview() abort
if s:has_nvim_ghost_text
call nvim_buf_del_extmark(0, copilot#NvimNs(), 1)
elseif s:has_vim_ghost_text
call prop_remove({'type': s:hlgroup, 'all': v:true})
call prop_remove({'type': s:annot_hlgroup, 'all': v:true})
endif
endfunction
function! s:UpdatePreview() abort
try
let [text, outdent, delete, item] = s:SuggestionTextWithAdjustments()
let text = split(text, "\r\n\\=\\|\n", 1)
if empty(text[-1])
call remove(text, -1)
endif
if empty(text) || !s:has_ghost_text
return s:ClearPreview()
endif
if exists('b:_copilot.cycling_callbacks')
let annot = '(1/…)'
elseif exists('b:_copilot.cycling')
let annot = '(' . (b:_copilot.choice + 1) . '/' . len(b:_copilot.suggestions) . ')'
else
let annot = ''
endif
call s:ClearPreview()
if s:has_nvim_ghost_text
let data = {'id': 1}
let data.virt_text_pos = 'overlay'
let append = strpart(getline('.'), col('.') - 1 + delete)
let data.virt_text = [[text[0] . append . repeat(' ', delete - len(text[0])), s:hlgroup]]
if len(text) > 1
let data.virt_lines = map(text[1:-1], { _, l -> [[l, s:hlgroup]] })
if !empty(annot)
let data.virt_lines[-1] += [[' '], [annot, s:annot_hlgroup]]
endif
elseif len(annot)
let data.virt_text += [[' '], [annot, s:annot_hlgroup]]
endif
let data.hl_mode = 'combine'
call nvim_buf_set_extmark(0, copilot#NvimNs(), line('.')-1, col('.')-1, data)
elseif s:has_vim_ghost_text
let new_suffix = text[0]
let current_suffix = getline('.')[col('.') - 1 :]
let inset = ''
while delete > 0 && !empty(new_suffix)
let last_char = matchstr(new_suffix, '.$')
let new_suffix = matchstr(new_suffix, '^.\{-\}\ze.$')
if last_char ==# matchstr(current_suffix, '.$')
if !empty(inset)
call prop_add(line('.'), col('.') + len(current_suffix), {'type': s:hlgroup, 'text': inset})
let inset = ''
endif
let current_suffix = matchstr(current_suffix, '^.\{-\}\ze.$')
let delete -= 1
else
let inset = last_char . inset
endif
endwhile
if !empty(new_suffix . inset)
call prop_add(line('.'), col('.'), {'type': s:hlgroup, 'text': new_suffix . inset})
endif
for line in text[1:]
call prop_add(line('.'), 0, {'type': s:hlgroup, 'text_align': 'below', 'text': line})
endfor
if !empty(annot)
call prop_add(line('.'), col('$'), {'type': s:annot_hlgroup, 'text': ' ' . annot})
endif
endif
call copilot#Notify('textDocument/didShowCompletion', {'item': item})
catch
return copilot#logger#Exception()
endtry
endfunction
function! s:HandleTriggerResult(state, result) abort
let a:state.suggestions = type(a:result) == type([]) ? a:result : get(empty(a:result) ? {} : a:result, 'items', [])
let a:state.choice = 0
if get(b:, '_copilot') is# a:state
call s:UpdatePreview()
endif
endfunction
function! s:HandleTriggerError(state, result) abort
let a:state.suggestions = []
let a:state.choice = 0
let a:state.error = a:result
if get(b:, '_copilot') is# a:state
call s:UpdatePreview()
endif
endfunction
function! copilot#Suggest() abort
if !s:Running()
return ''
endif
try
call copilot#Complete(function('s:HandleTriggerResult'), function('s:HandleTriggerError'))
catch
call copilot#logger#Exception()
endtry
return ''
endfunction
function! s:Trigger(bufnr, timer) abort
let timer = get(g:, '_copilot_timer', -1)
if a:bufnr !=# bufnr('') || a:timer isnot# timer || mode() !=# 'i'
return
endif
unlet! g:_copilot_timer
return copilot#Suggest()
endfunction
function! copilot#Schedule() abort
if !s:has_ghost_text || !s:Running() || !copilot#Enabled()
call copilot#Clear()
return
endif
call s:UpdatePreview()
let delay = get(g:, 'copilot_idle_delay', 45)
call timer_stop(get(g:, '_copilot_timer', -1))
let g:_copilot_timer = timer_start(delay, function('s:Trigger', [bufnr('')]))
endfunction
function! s:Attach(bufnr, ...) abort
try
return copilot#Client().Attach(a:bufnr)
catch
call copilot#logger#Exception()
endtry
endfunction
function! copilot#OnFileType() abort
if empty(s:BufferDisabled()) && &l:modifiable && &l:buflisted
call copilot#util#Defer(function('s:Attach'), bufnr(''))
endif
endfunction
function! s:Focus(bufnr, ...) abort
if s:Running() && copilot#Client().IsAttached(a:bufnr)
call copilot#Client().Notify('textDocument/didFocus', {'textDocument': {'uri': copilot#Client().Attach(a:bufnr).uri}})
endif
endfunction
function! copilot#OnBufEnter() abort
let bufnr = bufnr('')
call copilot#util#Defer(function('s:Focus'), bufnr)
endfunction
function! copilot#OnInsertLeavePre() abort
call copilot#Clear()
call s:ClearPreview()
endfunction
function! copilot#OnInsertEnter() abort
return copilot#Schedule()
endfunction
function! copilot#OnCompleteChanged() abort
if s:HideDuringCompletion()
return copilot#Clear()
else
return copilot#Schedule()
endif
endfunction
function! copilot#OnCursorMovedI() abort
return copilot#Schedule()
endfunction
function! copilot#OnBufUnload() abort
endfunction
function! copilot#OnVimLeavePre() abort
endfunction
function! copilot#TextQueuedForInsertion() abort
try
return remove(s:, 'suggestion_text')
catch
return ''
endtry
endfunction
function! copilot#Accept(...) abort
let s = copilot#GetDisplayedSuggestion()
if !empty(s.text)
unlet! b:_copilot
let text = ''
if a:0 > 1
let text = substitute(matchstr(s.text, "\n*" . '\%(' . a:2 .'\)'), "\n*$", '', '')
endif
if empty(text)
let text = s.text
endif
if text ==# s.text && has_key(s.item, 'command')
call copilot#Request('workspace/executeCommand', s.item.command)
else
let line_text = strpart(getline('.'), 0, col('.') - 1) . text
call copilot#Notify('textDocument/didPartiallyAcceptCompletion', {
\ 'item': s.item,
\ 'acceptedLength': copilot#util#UTF16Width(line_text) - s.item.range.start.character})
endif
call s:ClearPreview()
let s:suggestion_text = text
let recall = text =~# "\n" ? "\<C-R>\<C-O>=" : "\<C-R>\<C-R>="
return repeat("\<Left>\<Del>", s.outdentSize) . repeat("\<Del>", s.deleteSize) .
\ recall . "copilot#TextQueuedForInsertion()\<CR>" . (a:0 > 1 ? '' : "\<End>")
endif
let default = get(g:, 'copilot_tab_fallback', pumvisible() ? "\<C-N>" : "\t")
if !a:0
return default
elseif type(a:1) == v:t_string
return a:1
elseif type(a:1) == v:t_func
try
return call(a:1, [])
catch
return default
endtry
else
return default
endif
endfunction
function! copilot#AcceptWord(...) abort
return copilot#Accept(a:0 ? a:1 : '', '\%(\k\@!.\)*\k*')
endfunction
function! copilot#AcceptLine(...) abort
return copilot#Accept(a:0 ? a:1 : "\r", "[^\n]\\+")
endfunction
function! s:BrowserCallback(into, code) abort
let a:into.code = a:code
endfunction
function! copilot#Browser() abort
if type(get(g:, 'copilot_browser')) == v:t_list
let cmd = copy(g:copilot_browser)
elseif type(get(g:, 'open_command')) == v:t_list
let cmd = copy(g:open_command)
elseif has('win32')
let cmd = ['rundll32', 'url.dll,FileProtocolHandler']
elseif has('mac')
let cmd = ['open']
elseif executable('wslview')
return ['wslview']
elseif executable('xdg-open')
return ['xdg-open']
else
return []
endif
if executable(get(cmd, 0, ''))
return cmd
else
return []
endif
endfunction
let s:commands = {}
function! s:EnabledStatusMessage() abort
let buf_disabled = s:BufferDisabled()
if !s:has_ghost_text
if has('nvim')
return "Neovim 0.6 required to support ghost text"
else
return "Vim " . s:vim_minimum_version . " required to support ghost text"
endif
elseif !get(g:, 'copilot_enabled', 1)
return 'Disabled globally by :Copilot disable'
elseif buf_disabled is# 5
return 'Disabled for current buffer by buftype=' . &buftype
elseif buf_disabled is# 4
return 'Disabled for current buffer by b:copilot_enabled'
elseif buf_disabled is# 3
return 'Disabled for current buffer by b:copilot_disabled'
elseif buf_disabled is# 2
return 'Disabled for filetype=' . &filetype . ' by internal default'
elseif buf_disabled
return 'Disabled for filetype=' . &filetype . ' by g:copilot_filetypes'
elseif !copilot#Enabled()
return 'BUG: Something is wrong with enabling/disabling'
else
return ''
endif
endfunction
function! s:VerifySetup() abort
let error = copilot#Client().StartupError()
if !empty(error)
echo 'Copilot: ' . error
return
endif
let status = copilot#Call('checkStatus', {})
if !has_key(status, 'user')
echo 'Copilot: Not authenticated. Invoke :Copilot setup'
return
endif
if status.status ==# 'NoTelemetryConsent'
echo 'Copilot: Telemetry terms not accepted. Invoke :Copilot setup'
return
endif
if status.status ==# 'NotAuthorized'
echo "Copilot: You don't have access to GitHub Copilot. Sign up by visiting https://github.com/settings/copilot"
return
endif
return 1
endfunction
function! s:commands.status(opts) abort
if !s:VerifySetup()
return
endif
if exists('s:client.status.status') && s:client.status.status =~# 'Warning\|Error'
echo 'Copilot: ' . s:client.status.status
if !empty(get(s:client.status, 'message', ''))
echon ': ' . s:client.status.message
endif
return
endif
let status = s:EnabledStatusMessage()
if !empty(status)
echo 'Copilot: ' . status
return
endif
echo 'Copilot: Ready'
call s:EditorVersionWarning()
endfunction
function! s:commands.signout(opts) abort
let status = copilot#Call('checkStatus', {'options': {'localChecksOnly': v:true}})
if has_key(status, 'user')
echo 'Copilot: Signed out as GitHub user ' . status.user
else
echo 'Copilot: Not signed in'
endif
call copilot#Call('signOut', {})
endfunction
function! s:commands.setup(opts) abort
let startup_error = copilot#Client().StartupError()
if !empty(startup_error)
echo 'Copilot: ' . startup_error
return
endif
let browser = copilot#Browser()
let status = copilot#Call('checkStatus', {})
if has_key(status, 'user')
let data = {'status': 'AlreadySignedIn', 'user': status.user}
else
let data = copilot#Call('signInInitiate', {})
endif
if has_key(data, 'verificationUri')
let uri = data.verificationUri
if has('clipboard')
try
let @+ = data.userCode
catch
endtry
try
let @* = data.userCode
catch
endtry
endif
let codemsg = "First copy your one-time code: " . data.userCode . "\n"
try
if len(&mouse)
let mouse = &mouse
set mouse=
endif
if get(a:opts, 'bang')
call s:Echo(codemsg . "In your browser, visit " . uri)
elseif len(browser)
call input(codemsg . "Press ENTER to open GitHub in your browser\n")
let status = {}
call copilot#job#Stream(browser + [uri], v:null, v:null, function('s:BrowserCallback', [status]))
let time = reltime()
while empty(status) && reltimefloat(reltime(time)) < 5
sleep 10m
endwhile
if get(status, 'code', browser[0] !=# 'xdg-open') != 0
call s:Echo("Failed to open browser. Visit " . uri)
else
call s:Echo("Opened " . uri)
endif
else
call s:Echo(codemsg . "Could not find browser. Visit " . uri)
endif
call s:Echo("Waiting (could take up to 10 seconds)")
let request = copilot#Request('signInConfirm', {'userCode': data.userCode}).Wait()
finally
if exists('mouse')
let &mouse = mouse
endif
endtry
if request.status ==# 'error'
return 'echoerr ' . string('Copilot: Authentication failure: ' . request.error.message)
else
let status = request.result
endif
elseif get(data, 'status', '') isnot# 'AlreadySignedIn'
return 'echoerr ' . string('Copilot: Something went wrong')
endif
let user = get(status, 'user', '<unknown>')
echo 'Copilot: Authenticated as GitHub user ' . user
endfunction
let s:commands.auth = s:commands.setup
let s:commands.signin = s:commands.setup
function! s:commands.help(opts) abort
return a:opts.mods . ' help ' . (len(a:opts.arg) ? ':Copilot_' . a:opts.arg : 'copilot')
endfunction
function! s:commands.version(opts) abort
echo 'copilot.vim ' .copilot#client#EditorPluginInfo().version
let editorInfo = copilot#client#EditorInfo()
echo editorInfo.name . ' ' . editorInfo.version
if s:Running()
let versions = s:client.Request('getVersion', {})
if exists('s:client.serverInfo.version')
echo s:client.serverInfo.name . ' ' . s:client.serverInfo.version
else
echo 'GitHub Copilot Language Server ' . versions.Await().version
endif
if exists('s:client.node_version')
echo 'Node.js ' . s:client.node_version
else
echo 'Node.js ' . substitute(get(versions.Await(), 'runtimeVersion', '?'), '^node/', '', 'g')
endif
else
echo 'Not running'
if exists('s:client.node_version')
echo 'Node.js ' . s:client.node_version
endif
endif
if has('win32')
echo 'Windows'
elseif has('macunix')
echo 'macOS'
elseif !has('unix')
echo 'Unknown OS'
elseif isdirectory('/sys/kernel')
echo 'Linux'
else
echo 'UNIX'
endif
call s:EditorVersionWarning()
endfunction
function! s:UpdateEditorConfiguration() abort
try
if s:Running()
call copilot#Notify('notifyChangeConfiguration', {'settings': s:EditorConfiguration()})
endif
catch
call copilot#logger#Exception()
endtry
endfunction
let s:feedback_url = 'https://github.com/orgs/community/discussions/categories/copilot'
function! s:commands.feedback(opts) abort
echo s:feedback_url
let browser = copilot#Browser()
if len(browser)
call copilot#job#Stream(browser + [s:feedback_url], v:null, v:null, v:null)
endif
endfunction
function! s:commands.restart(opts) abort
call s:Stop()
echo 'Copilot: Restarting language server'
call s:Start()
endfunction
function! s:commands.disable(opts) abort
let g:copilot_enabled = 0
call s:UpdateEditorConfiguration()
endfunction
function! s:commands.enable(opts) abort
let g:copilot_enabled = 1
call s:UpdateEditorConfiguration()
endfunction
function! s:commands.panel(opts) abort
if s:VerifySetup()
return copilot#panel#Open(a:opts)
endif
endfunction
function! s:commands.log(opts) abort
return a:opts.mods . ' split +$ copilot:///log'
endfunction
function! copilot#CommandComplete(arg, lead, pos) abort
let args = matchstr(strpart(a:lead, 0, a:pos), 'C\%[opilot][! ] *\zs.*')
if args !~# ' '
return sort(filter(map(keys(s:commands), { k, v -> tr(v, '_', '-') }),
\ { k, v -> strpart(v, 0, len(a:arg)) ==# a:arg }))
else
return []
endif
endfunction
function! copilot#Command(line1, line2, range, bang, mods, arg) abort
let cmd = matchstr(a:arg, '^\%(\\.\|\S\)\+')
let arg = matchstr(a:arg, '\s\zs\S.*')
if !empty(cmd) && !has_key(s:commands, tr(cmd, '-', '_'))
return 'echoerr ' . string('Copilot: unknown command ' . string(cmd))
endif
try
if empty(cmd)
if !s:Running()
let cmd = 'restart'
else
try
let opts = copilot#Call('checkStatus', {'options': {'localChecksOnly': v:true}})
if opts.status !=# 'OK' && opts.status !=# 'MaybeOK'
let cmd = 'setup'
else
let cmd = 'panel'
endif
catch
call copilot#logger#Exception()
let cmd = 'log'
endtry
endif
endif
let opts = {'line1': a:line1, 'line2': a:line2, 'range': a:range, 'bang': a:bang, 'mods': a:mods, 'arg': arg}
let retval = s:commands[tr(cmd, '-', '_')](opts)
if type(retval) == v:t_string
return retval
else
return ''
endif
catch /^Copilot:/
return 'echoerr ' . string(v:exception)
endtry
endfunction

View File

@@ -1,764 +0,0 @@
scriptencoding utf-8
let s:plugin_version = copilot#version#String()
let s:error_canceled = {'code': -32800, 'message': 'Canceled'}
let s:error_exit = {'code': -32097, 'message': 'Process exited'}
let s:error_connection_inactive = {'code': -32096, 'message': 'Connection inactive'}
let s:root = expand('<sfile>:h:h:h')
if !exists('s:instances')
let s:instances = {}
endif
" allow sourcing this file to reload the Lua file too
if has('nvim')
lua package.loaded._copilot = nil
endif
function! s:Warn(msg) abort
if !empty(get(g:, 'copilot_no_startup_warnings'))
return
endif
echohl WarningMsg
echomsg 'Copilot: ' . a:msg
echohl NONE
endfunction
function! s:VimClose() dict abort
if !has_key(self, 'job')
return
endif
let job = self.job
if has_key(self, 'kill')
call job_stop(job, 'kill')
call copilot#logger#Warn('Process forcefully terminated')
return
endif
let self.kill = v:true
let self.shutdown = self.Request('shutdown', {}, function(self.Notify, ['exit']))
call timer_start(2000, { _ -> job_stop(job, 'kill') })
call copilot#logger#Debug('Process shutdown initiated')
endfunction
function! s:LogSend(request, line) abort
return '--> ' . a:line
endfunction
function! s:RejectRequest(request, error) abort
if a:request.status !=# 'running'
return
endif
let a:request.waiting = {}
call remove(a:request, 'resolve')
let reject = remove(a:request, 'reject')
let a:request.status = 'error'
let a:request.error = deepcopy(a:error)
for Cb in reject
let a:request.waiting[timer_start(0, function('s:Callback', [a:request, 'error', Cb]))] = 1
endfor
if index([s:error_canceled.code, s:error_connection_inactive.code], a:error.code) != -1
return
endif
let msg = 'Method ' . a:request.method . ' errored with E' . a:error.code . ': ' . json_encode(a:error.message)
if empty(reject)
call copilot#logger#Error(msg)
else
call copilot#logger#Debug(msg)
endif
endfunction
function! s:AfterInitialized(fn, ...) dict abort
call add(self.after_initialized, function(a:fn, a:000))
endfunction
function! s:Send(instance, request) abort
if !has_key(a:instance, 'job')
return v:false
endif
try
call ch_sendexpr(a:instance.job, a:request)
return v:true
catch /^Vim\%((\a\+)\)\=:E906:/
let a:instance.kill = v:true
let job = remove(a:instance, 'job')
call job_stop(job)
call timer_start(2000, { _ -> job_stop(job, 'kill') })
call copilot#logger#Warn('Terminating process after failed write')
return v:false
catch /^Vim\%((\a\+)\)\=:E631:/
return v:false
endtry
endfunction
function! s:VimNotify(method, params) dict abort
let request = {'method': a:method, 'params': a:params}
call self.AfterInitialized(function('s:Send', [self, request]))
endfunction
function! s:RequestWait() dict abort
while self.status ==# 'running'
sleep 1m
endwhile
while !empty(get(self, 'waiting', {}))
sleep 1m
endwhile
return self
endfunction
function! s:RequestAwait() dict abort
call self.Wait()
if has_key(self, 'result')
return self.result
endif
throw 'Copilot:E' . self.error.code . ': ' . self.error.message
endfunction
function! s:RequestClient() dict abort
return get(s:instances, self.client_id, v:null)
endfunction
if !exists('s:id')
let s:id = 0
endif
if !exists('s:progress_token_id')
let s:progress_token_id = 0
endif
function! s:SetUpRequest(instance, id, method, params, progress, ...) abort
let request = {
\ 'client_id': a:instance.id,
\ 'id': a:id,
\ 'method': a:method,
\ 'params': a:params,
\ 'Client': function('s:RequestClient'),
\ 'Wait': function('s:RequestWait'),
\ 'Await': function('s:RequestAwait'),
\ 'Cancel': function('s:RequestCancel'),
\ 'resolve': [],
\ 'reject': [],
\ 'progress': a:progress,
\ 'status': 'running'}
let args = a:000[2:-1]
if len(args)
if !empty(a:1)
call add(request.resolve, { v -> call(a:1, [v] + args)})
endif
if !empty(a:2)
call add(request.reject, { v -> call(a:2, [v] + args)})
endif
return request
endif
if a:0 && !empty(a:1)
call add(request.resolve, a:1)
endif
if a:0 > 1 && !empty(a:2)
call add(request.reject, a:2)
endif
return request
endfunction
function! s:UrlEncode(str) abort
return substitute(iconv(a:str, 'latin1', 'utf-8'),'[^A-Za-z0-9._~!$&''()*+,;=:@/-]','\="%".printf("%02X",char2nr(submatch(0)))','g')
endfunction
let s:slash = exists('+shellslash') ? '\' : '/'
function! s:UriFromBufnr(bufnr) abort
let absolute = tr(bufname(a:bufnr), s:slash, '/')
if absolute !~# '^\a\+:\|^/\|^$' && getbufvar(a:bufnr, 'buftype') =~# '^\%(nowrite\)\=$'
let absolute = substitute(tr(getcwd(), s:slash, '/'), '/\=$', '/', '') . absolute
endif
return s:UriFromPath(absolute)
endfunction
function! s:UriFromPath(absolute) abort
let absolute = a:absolute
if has('win32') && absolute =~# '^\a://\@!'
return 'file:///' . strpart(absolute, 0, 2) . s:UrlEncode(strpart(absolute, 2))
elseif absolute =~# '^/'
return 'file://' . s:UrlEncode(absolute)
elseif absolute =~# '^\a[[:alnum:].+-]*:\|^$'
return absolute
else
return ''
endif
endfunction
function! s:BufferText(bufnr) abort
return join(getbufline(a:bufnr, 1, '$'), "\n") . "\n"
endfunction
let s:valid_request_key = '^\%(id\|method\|params\)$'
function! s:SendRequest(instance, request, ...) abort
if !has_key(a:instance, 'job') || get(a:instance, 'shutdown', a:request) isnot# a:request
return s:RejectRequest(a:request, s:error_connection_inactive)
endif
let json = filter(copy(a:request), 'v:key =~# s:valid_request_key')
if empty(s:Send(a:instance, json)) && has_key(a:request, 'id') && has_key(a:instance.requests, a:request.id)
call s:RejectRequest(remove(a:instance.requests, a:request.id), {'code': -32099, 'message': 'Write failed'})
endif
endfunction
function! s:RegisterWorkspaceFolderForBuffer(instance, buf) abort
let root = getbufvar(a:buf, 'workspace_folder')
if type(root) != v:t_string
return
endif
let root = s:UriFromPath(substitute(root, '[\/]$', '', ''))
if empty(root) || has_key(a:instance.workspaceFolders, root)
return
endif
let a:instance.workspaceFolders[root] = v:true
call a:instance.Notify('workspace/didChangeWorkspaceFolders', {'event': {'added': [{'uri': root, 'name': fnamemodify(root, ':t')}], 'removed': []}})
endfunction
function! s:PreprocessParams(instance, params) abort
let bufnr = v:null
for doc in filter([get(a:params, 'textDocument', {})], 'type(get(v:val, "uri", "")) == v:t_number')
let bufnr = doc.uri
call s:RegisterWorkspaceFolderForBuffer(a:instance, bufnr)
call extend(doc, a:instance.Attach(bufnr))
endfor
let progress_tokens = []
for key in keys(a:params)
if key =~# 'Token$' && type(a:params[key]) == v:t_func
let s:progress_token_id += 1
let a:instance.progress[s:progress_token_id] = a:params[key]
call add(progress_tokens, s:progress_token_id)
let a:params[key] = s:progress_token_id
endif
endfor
return [bufnr, progress_tokens]
endfunction
function! s:VimAttach(bufnr) dict abort
if !bufloaded(a:bufnr)
return {'uri': '', 'version': 0}
endif
let bufnr = a:bufnr
let doc = {
\ 'uri': s:UriFromBufnr(bufnr),
\ 'version': getbufvar(bufnr, 'changedtick', 0),
\ 'languageId': getbufvar(bufnr, '&filetype'),
\ }
if has_key(self.open_buffers, bufnr) && (
\ self.open_buffers[bufnr].uri !=# doc.uri ||
\ self.open_buffers[bufnr].languageId !=# doc.languageId)
call self.Notify('textDocument/didClose', {'textDocument': {'uri': self.open_buffers[bufnr].uri}})
call remove(self.open_buffers, bufnr)
endif
if !has_key(self.open_buffers, bufnr)
call self.Notify('textDocument/didOpen', {'textDocument': extend({'text': s:BufferText(bufnr)}, doc)})
let self.open_buffers[bufnr] = doc
else
call self.Notify('textDocument/didChange', {
\ 'textDocument': {'uri': doc.uri, 'version': doc.version},
\ 'contentChanges': [{'text': s:BufferText(bufnr)}]})
let self.open_buffers[bufnr].version = doc.version
endif
return doc
endfunction
function! s:VimIsAttached(bufnr) dict abort
return bufloaded(a:bufnr) && has_key(self.open_buffers, a:bufnr) ? v:true : v:false
endfunction
function! s:VimRequest(method, params, ...) dict abort
let s:id += 1
let params = deepcopy(a:params)
let [_, progress] = s:PreprocessParams(self, params)
let request = call('s:SetUpRequest', [self, s:id, a:method, params, progress] + a:000)
call self.AfterInitialized(function('s:SendRequest', [self, request]))
let self.requests[s:id] = request
return request
endfunction
function! s:Call(method, params, ...) dict abort
let request = call(self.Request, [a:method, a:params] + a:000)
if a:0
return request
endif
return request.Await()
endfunction
function! s:Cancel(request) dict abort
if has_key(self.requests, get(a:request, 'id', ''))
call self.Notify('$/cancelRequest', {'id': a:request.id})
call s:RejectRequest(remove(self.requests, a:request.id), s:error_canceled)
endif
endfunction
function! s:RequestCancel() dict abort
let instance = self.Client()
if !empty(instance)
call instance.Cancel(self)
elseif get(self, 'status', '') ==# 'running'
call s:RejectRequest(self, s:error_canceled)
endif
return self
endfunction
function! s:DispatchMessage(instance, method, handler, id, params, ...) abort
try
let response = {'result': call(a:handler, [a:params, a:instance])}
if response.result is# 0
let response.result = v:null
endif
catch
call copilot#logger#Exception('lsp.request.' . a:method)
let response = {'error': {'code': -32000, 'message': v:exception}}
endtry
if a:id isnot# v:null
call s:Send(a:instance, extend({'id': a:id}, response))
endif
if !has_key(s:notifications, a:method)
return response
endif
endfunction
function! s:OnMessage(instance, body, ...) abort
if !has_key(a:body, 'method')
return s:OnResponse(a:instance, a:body)
endif
let request = a:body
let id = get(request, 'id', v:null)
let params = get(request, 'params', v:null)
if has_key(a:instance.methods, request.method)
return s:DispatchMessage(a:instance, request.method, a:instance.methods[request.method], id, params)
elseif id isnot# v:null
call s:Send(a:instance, {"id": id, "error": {"code": -32700, "message": "Method not found: " . request.method}})
call copilot#logger#Debug('Unexpected request ' . request.method . ' called with ' . json_encode(params))
elseif request.method !~# '^\$/'
call copilot#logger#Debug('Unexpected notification ' . request.method . ' called with ' . json_encode(params))
endif
endfunction
function! s:OnResponse(instance, response, ...) abort
let response = a:response
let id = get(a:response, 'id', v:null)
if !has_key(a:instance.requests, id)
return
endif
let request = remove(a:instance.requests, id)
for progress_token in request.progress
if has_key(a:instance.progress, progress_token)
call remove(a:instance.progress, progress_token)
endif
endfor
if request.status !=# 'running'
return
endif
if has_key(response, 'result')
let request.waiting = {}
let resolve = remove(request, 'resolve')
call remove(request, 'reject')
let request.status = 'success'
let request.result = response.result
for Cb in resolve
let request.waiting[timer_start(0, function('s:Callback', [request, 'result', Cb]))] = 1
endfor
else
call s:RejectRequest(request, response.error)
endif
endfunction
function! s:OnErr(instance, ch, line, ...) abort
if !has_key(a:instance, 'serverInfo')
call copilot#logger#Bare('<-! ' . a:line)
endif
endfunction
function! s:OnExit(instance, code, ...) abort
let a:instance.exit_status = a:code
if has_key(a:instance, 'job')
call remove(a:instance, 'job')
endif
if has_key(a:instance, 'client_id')
call remove(a:instance, 'client_id')
endif
let message = 'Process exited with status ' . a:code
if a:code >= 18 && a:code < 100
let message = 'Node.js too old. ' .
\ (get(a:instance.node, 0, 'node') ==# 'node' ? 'Upgrade' : 'Change g:copilot_node_command') .
\ ' to ' . a:code . '.x or newer'
endif
if !has_key(a:instance, 'serverInfo') && !has_key(a:instance, 'startup_error')
let a:instance.startup_error = message
endif
for id in sort(keys(a:instance.requests), { a, b -> +a > +b })
call s:RejectRequest(remove(a:instance.requests, id), s:error_exit)
endfor
if has_key(a:instance, 'after_initialized')
let a:instance.AfterInitialized = function('copilot#util#Defer')
for Fn in remove(a:instance, 'after_initialized')
call copilot#util#Defer(Fn)
endfor
endif
call copilot#util#Defer({ -> get(s:instances, a:instance.id) is# a:instance ? remove(s:instances, a:instance.id) : {} })
if a:code == 0
call copilot#logger#Info(message)
else
call copilot#logger#Warn(message)
if !has_key(a:instance, 'kill')
call copilot#util#Defer(function('s:Warn'), message)
endif
endif
endfunction
function! copilot#client#LspInit(id, initialize_result) abort
if !has_key(s:instances, a:id)
return
endif
call s:PostInit(a:initialize_result, s:instances[a:id])
endfunction
function! copilot#client#LspExit(id, code, signal) abort
if !has_key(s:instances, a:id)
return
endif
let instance = remove(s:instances, a:id)
call s:OnExit(instance, a:code)
endfunction
function! copilot#client#LspResponse(id, opts, ...) abort
if !has_key(s:instances, a:id)
return
endif
call s:OnResponse(s:instances[a:id], a:opts)
endfunction
function! s:NvimAttach(bufnr) dict abort
if !bufloaded(a:bufnr)
return {'uri': '', 'version': 0}
endif
call luaeval('pcall(vim.lsp.buf_attach_client, _A[1], _A[2])', [a:bufnr, self.id])
return luaeval('{uri = vim.uri_from_bufnr(_A), version = vim.lsp.util.buf_versions[_A]}', a:bufnr)
endfunction
function! s:NvimIsAttached(bufnr) dict abort
return bufloaded(a:bufnr) ? luaeval('vim.lsp.buf_is_attached(_A[1], _A[2])', [a:bufnr, self.id]) : v:false
endfunction
function! s:NvimRequest(method, params, ...) dict abort
let params = deepcopy(a:params)
let [bufnr, progress] = s:PreprocessParams(self, params)
let request = call('s:SetUpRequest', [self, v:null, a:method, params, progress] + a:000)
call self.AfterInitialized(function('s:NvimDoRequest', [self, request, bufnr]))
return request
endfunction
function! s:NvimDoRequest(client, request, bufnr) abort
let request = a:request
if has_key(a:client, 'client_id') && !has_key(a:client, 'kill')
let request.id = eval("v:lua.require'_copilot'.lsp_request(a:client.id, a:request.method, a:request.params, a:bufnr)")
endif
if request.id isnot# v:null
let a:client.requests[request.id] = request
else
if has_key(a:client, 'client_id')
call copilot#client#LspExit(a:client.client_id, -1, -1)
endif
call copilot#util#Defer(function('s:RejectRequest'), request, s:error_connection_inactive)
endif
return request
endfunction
function! s:NvimClose() dict abort
if !has_key(self, 'client_id')
return
endif
let self.kill = v:true
return luaeval('vim.lsp.get_client_by_id(_A).stop()', self.client_id)
endfunction
function! s:NvimNotify(method, params) dict abort
call self.AfterInitialized(function('s:NvimDoNotify', [self.client_id, a:method, a:params]))
endfunction
function! s:NvimDoNotify(client_id, method, params) abort
return eval("v:lua.require'_copilot'.rpc_notify(a:client_id, a:method, a:params)")
endfunction
function! copilot#client#LspHandle(id, request) abort
if !has_key(s:instances, a:id)
return
endif
return s:OnMessage(s:instances[a:id], a:request)
endfunction
let s:script_name = 'dist/language-server.js'
function! s:Command() abort
if !has('nvim-0.7') && v:version < 900
return [[], [], 'Vim version too old']
endif
let script = get(g:, 'copilot_command', '')
if type(script) == type('')
let script = [expand(script)]
endif
if empty(script) || !filereadable(script[0])
let script = [s:root . '/' . s:script_name]
if !filereadable(script[0])
return [[], [], 'Could not find ' . s:script_name . ' (bad install?)']
endif
elseif script[0] !~# '\.js$'
return [[], script + ['--stdio'], '']
endif
let node = get(g:, 'copilot_node_command', '')
if empty(node)
let node = ['node']
elseif type(node) == type('')
let node = [expand(node)]
endif
if !executable(get(node, 0, ''))
if get(node, 0, '') ==# 'node'
return [[], [], 'Node.js not found in PATH']
else
return [[], [], 'Node.js executable `' . get(node, 0, '') . "' not found"]
endif
endif
return [node, script + ['--stdio'], '']
endfunction
function! s:UrlDecode(str) abort
return substitute(a:str, '%\(\x\x\)', '\=iconv(nr2char("0x".submatch(1)), "utf-8", "latin1")', 'g')
endfunction
function! copilot#client#EditorInfo() abort
if !exists('s:editor_version')
if has('nvim')
let s:editor_version = matchstr(execute('version'), 'NVIM v\zs[^[:space:]]\+')
else
let s:editor_version = (v:version / 100) . '.' . (v:version % 100) . (exists('v:versionlong') ? printf('.%04d', v:versionlong % 10000) : '')
endif
endif
return {'name': has('nvim') ? 'Neovim': 'Vim', 'version': s:editor_version}
endfunction
function! copilot#client#EditorPluginInfo() abort
return {'name': 'copilot.vim', 'version': s:plugin_version}
endfunction
function! copilot#client#Settings() abort
let settings = {
\ 'http': {
\ 'proxy': get(g:, 'copilot_proxy', v:null),
\ 'proxyStrictSSL': get(g:, 'copilot_proxy_strict_ssl', v:null)},
\ 'github-enterprise': {'uri': get(g:, 'copilot_auth_provider_url', v:null)},
\ }
if type(settings.http.proxy) ==# v:t_string && settings.http.proxy =~# '^[^/]\+$'
let settings.http.proxy = 'http://' . settings.http.proxy
endif
if type(get(g:, 'copilot_settings')) == v:t_dict
call extend(settings, g:copilot_settings)
endif
return settings
endfunction
function! s:PostInit(result, instance) abort
let a:instance.serverInfo = get(a:result, 'serverInfo', {})
if !has_key(a:instance, 'node_version') && has_key(a:result.serverInfo, 'nodeVersion')
let a:instance.node_version = a:result.serverInfo.nodeVersion
endif
let a:instance.AfterInitialized = function('copilot#util#Defer')
for Fn in remove(a:instance, 'after_initialized')
call copilot#util#Defer(Fn)
endfor
endfunction
function! s:InitializeResult(result, instance) abort
call s:Send(a:instance, {'method': 'initialized', 'params': {}})
call s:PostInit(a:result, a:instance)
endfunction
function! s:InitializeError(error, instance) abort
if !has_key(a:instance, 'startup_error')
let a:instance.startup_error = 'Unexpected error E' . a:error.code . ' initializing language server: ' . a:error.message
call a:instance.Close()
endif
endfunction
function! s:StartupError() dict abort
while (has_key(self, 'job') || has_key(self, 'client_id')) && !has_key(self, 'startup_error') && !has_key(self, 'serverInfo')
sleep 10m
endwhile
if has_key(self, 'serverInfo')
return ''
else
return get(self, 'startup_error', 'Something unexpected went wrong spawning the language server')
endif
endfunction
function! s:StatusNotification(params, instance) abort
let a:instance.status = a:params
endfunction
function! s:Nop(...) abort
return v:null
endfunction
function! s:False(...) abort
return v:false
endfunction
function! s:Progress(params, instance) abort
if has_key(a:instance.progress, a:params.token)
call a:instance.progress[a:params.token](a:params.value)
endif
endfunction
let s:notifications = {
\ '$/progress': function('s:Progress'),
\ 'featureFlagsNotification': function('s:Nop'),
\ 'statusNotification': function('s:StatusNotification'),
\ 'window/logMessage': function('copilot#handlers#window_logMessage'),
\ }
let s:vim_handlers = {
\ 'window/showMessageRequest': function('copilot#handlers#window_showMessageRequest'),
\ 'window/showDocument': function('copilot#handlers#window_showDocument'),
\ }
let s:vim_capabilities = {
\ 'workspace': {'workspaceFolders': v:true},
\ 'window': {'showDocument': {'support': v:true}},
\ }
function! copilot#client#New(...) abort
let opts = a:0 ? a:1 : {}
let instance = {'requests': {},
\ 'progress': {},
\ 'workspaceFolders': {},
\ 'after_initialized': [],
\ 'status': {'status': 'Starting', 'message': ''},
\ 'AfterInitialized': function('s:AfterInitialized'),
\ 'Close': function('s:Nop'),
\ 'Notify': function('s:False'),
\ 'Request': function('s:VimRequest'),
\ 'Attach': function('s:Nop'),
\ 'IsAttached': function('s:False'),
\ 'Call': function('s:Call'),
\ 'Cancel': function('s:Cancel'),
\ 'StartupError': function('s:StartupError'),
\ }
let instance.methods = copy(s:notifications)
let [node, argv, command_error] = s:Command()
if !empty(command_error)
let instance.id = -1
let instance.startup_error = command_error
call copilot#logger#Error(command_error)
return instance
endif
let instance.node = node
let command = node + argv
let opts = {}
let opts.initializationOptions = {
\ 'editorInfo': copilot#client#EditorInfo(),
\ 'editorPluginInfo': copilot#client#EditorPluginInfo(),
\ }
let opts.workspaceFolders = []
let settings = extend(copilot#client#Settings(), get(opts, 'editorConfiguration', {}))
if type(get(g:, 'copilot_workspace_folders')) == v:t_list
for folder in g:copilot_workspace_folders
if type(folder) == v:t_string && !empty(folder) && folder !~# '\*\*\|^/$'
for path in glob(folder . '/', 0, 1)
let uri = s:UriFromPath(substitute(path, '[\/]*$', '', ''))
call add(opts.workspaceFolders, {'uri': uri, 'name': fnamemodify(uri, ':t')})
endfor
elseif type(folder) == v:t_dict && has_key(v:t_dict, 'uri') && !empty(folder.uri) && has_key(folder, 'name')
call add(opts.workspaceFolders, folder)
endif
endfor
endif
for folder in opts.workspaceFolders
let instance.workspaceFolders[folder.uri] = v:true
endfor
if has('nvim')
call extend(instance, {
\ 'Close': function('s:NvimClose'),
\ 'Notify': function('s:NvimNotify'),
\ 'Request': function('s:NvimRequest'),
\ 'Attach': function('s:NvimAttach'),
\ 'IsAttached': function('s:NvimIsAttached'),
\ })
let instance.client_id = eval("v:lua.require'_copilot'.lsp_start_client(command, keys(instance.methods), opts, settings)")
let instance.id = instance.client_id
else
call extend(instance, {
\ 'Close': function('s:VimClose'),
\ 'Notify': function('s:VimNotify'),
\ 'Attach': function('s:VimAttach'),
\ 'IsAttached': function('s:VimIsAttached'),
\ })
let state = {'headers': {}, 'mode': 'headers', 'buffer': ''}
let instance.open_buffers = {}
let instance.methods = extend(s:vim_handlers, instance.methods)
let instance.job = job_start(command, {
\ 'cwd': copilot#job#Cwd(),
\ 'noblock': 1,
\ 'stoponexit': '',
\ 'in_mode': 'lsp',
\ 'out_mode': 'lsp',
\ 'out_cb': { j, d -> copilot#util#Defer(function('s:OnMessage'), instance, d) },
\ 'err_cb': function('s:OnErr', [instance]),
\ 'exit_cb': { j, d -> copilot#util#Defer(function('s:OnExit'), instance, d) },
\ })
let instance.id = job_info(instance.job).process
let opts.capabilities = s:vim_capabilities
let opts.processId = getpid()
let request = instance.Request('initialize', opts, function('s:InitializeResult'), function('s:InitializeError'), instance)
call call(remove(instance.after_initialized, 0), [])
call instance.Notify('workspace/didChangeConfiguration', {'settings': settings})
endif
let s:instances[instance.id] = instance
return instance
endfunction
function! copilot#client#Cancel(request) abort
if type(a:request) == type({}) && has_key(a:request, 'Cancel')
call a:request.Cancel()
endif
endfunction
function! s:Callback(request, type, callback, timer) abort
call remove(a:request.waiting, a:timer)
if has_key(a:request, a:type)
call a:callback(a:request[a:type])
endif
endfunction
function! copilot#client#Result(request, callback) abort
if has_key(a:request, 'resolve')
call add(a:request.resolve, a:callback)
elseif has_key(a:request, 'result')
let a:request.waiting[timer_start(0, function('s:Callback', [a:request, 'result', a:callback]))] = 1
endif
endfunction
function! copilot#client#Error(request, callback) abort
if has_key(a:request, 'reject')
call add(a:request.reject, a:callback)
elseif has_key(a:request, 'error')
let a:request.waiting[timer_start(0, function('s:Callback', [a:request, 'error', a:callback]))] = 1
endif
endfunction
function! s:CloseBuffer(bufnr) abort
for instance in values(s:instances)
try
if has_key(instance, 'job') && has_key(instance.open_buffers, a:bufnr)
let buffer = remove(instance.open_buffers, a:bufnr)
call instance.Notify('textDocument/didClose', {'textDocument': {'uri': buffer.uri}})
endif
catch
call copilot#logger#Exception()
endtry
endfor
endfunction
augroup copilot_close
autocmd!
if !has('nvim')
autocmd BufUnload * call s:CloseBuffer(+expand('<abuf>'))
endif
augroup END

View File

@@ -1,31 +0,0 @@
function! copilot#handlers#window_logMessage(params, ...) abort
call copilot#logger#Raw(get(a:params, 'type', 6), get(a:params, 'message', ''))
endfunction
function! copilot#handlers#window_showMessageRequest(params, ...) abort
let choice = inputlist([a:params.message . "\n\nRequest Actions:"] +
\ map(copy(get(a:params, 'actions', [])), { i, v -> (i + 1) . '. ' . v.title}))
return choice > 0 ? get(a:params.actions, choice - 1, v:null) : v:null
endfunction
function! s:BrowserCallback(into, code) abort
let a:into.code = a:code
endfunction
function! copilot#handlers#window_showDocument(params, ...) abort
echo a:params.uri
if empty(get(a:params, 'external'))
return {'success': v:false}
endif
let browser = copilot#Browser()
if empty(browser)
return {'success': v:false}
endif
let status = {}
call copilot#job#Stream(browser + [a:params.uri], v:null, v:null, function('s:BrowserCallback', [status]))
let time = reltime()
while empty(status) && reltimefloat(reltime(time)) < 1
sleep 10m
endwhile
return {'success': get(status, 'code') ? v:false : v:true}
endfunction

View File

@@ -1,106 +0,0 @@
scriptencoding utf-8
function! copilot#job#Nop(...) abort
endfunction
function! s:Jobs(job_or_jobs) abort
let jobs = type(a:job_or_jobs) == v:t_list ? copy(a:job_or_jobs) : [a:job_or_jobs]
call map(jobs, { k, v -> type(v) == v:t_dict ? get(v, 'job', '') : v })
call filter(jobs, { k, v -> type(v) !=# type('') })
return jobs
endfunction
let s:job_stop = exists('*job_stop') ? 'job_stop' : 'jobstop'
function! copilot#job#Stop(job) abort
for job in s:Jobs(a:job)
call call(s:job_stop, [job])
endfor
return copilot#job#Wait(a:job)
endfunction
let s:sleep = has('patch-8.2.2366') ? 'sleep! 1m' : 'sleep 1m'
function! copilot#job#Wait(jobs) abort
let jobs = s:Jobs(a:jobs)
if exists('*jobwait')
call jobwait(jobs)
else
for job in jobs
while ch_status(job) !=# 'closed' || job_status(job) ==# 'run'
exe s:sleep
endwhile
endfor
endif
return a:jobs
endfunction
function! s:VimExitCallback(result, exit_cb, job, data) abort
let a:result.exit_status = a:data
if !has_key(a:result, 'closed')
return
endif
call remove(a:result, 'closed')
call a:exit_cb(a:result.exit_status)
endfunction
function! s:VimCloseCallback(result, exit_cb, job) abort
if !has_key(a:result, 'exit_status')
let a:result.closed = v:true
return
endif
call a:exit_cb(a:result.exit_status)
endfunction
function! s:NvimCallback(cb, job, data, type) dict abort
let self[a:type][0] .= remove(a:data, 0)
call extend(self[a:type], a:data)
while len(self[a:type]) > 1
call a:cb(substitute(remove(self[a:type], 0), "\r$", '', ''))
endwhile
endfunction
function! s:NvimExitCallback(out_cb, err_cb, exit_cb, job, data, type) dict abort
if len(self.stderr[0])
call a:err_cb(substitute(self.stderr[0], "\r$", '', ''))
endif
call a:exit_cb(a:data)
endfunction
function! copilot#job#Cwd() abort
let home = expand("~")
if !isdirectory(home) && isdirectory($VIM)
return $VIM
endif
return home
endfunction
function! copilot#job#Stream(argv, out_cb, err_cb, ...) abort
let exit_status = []
let ExitCb = function(a:0 && !empty(a:1) ? a:1 : { e -> add(exit_status, e) }, a:000[2:-1])
let OutCb = function(empty(a:out_cb) ? 'copilot#job#Nop' : a:out_cb, a:000[2:-1])
let ErrCb = function(empty(a:err_cb) ? 'copilot#job#Nop' : a:err_cb, a:000[2:-1])
let state = {'headers': {}, 'mode': 'headers', 'buffer': ''}
if exists('*job_start')
let result = {}
let job = job_start(a:argv, {
\ 'cwd': copilot#job#Cwd(),
\ 'out_mode': 'raw',
\ 'out_cb': { j, d -> OutCb(d) },
\ 'err_cb': { j, d -> ErrCb(d) },
\ 'exit_cb': function('s:VimExitCallback', [result, ExitCb]),
\ 'close_cb': function('s:VimCloseCallback', [result, ExitCb]),
\ })
else
let jopts = {
\ 'cwd': copilot#job#Cwd(),
\ 'stderr': [''],
\ 'on_stdout': { j, d, t -> OutCb(join(d, "\n")) },
\ 'on_stderr': function('s:NvimCallback', [ErrCb]),
\ 'on_exit': function('s:NvimExitCallback', [OutCb, ErrCb, ExitCb])}
let job = jobstart(a:argv, jopts)
endif
if a:0
return job
endif
call copilot#job#Wait(job)
return exit_status[0]
endfunction

View File

@@ -1,105 +0,0 @@
if !exists('s:log_file')
let s:log_file = tempname() . '-copilot.log'
try
call writefile([], s:log_file)
catch
endtry
endif
let s:logs = []
function! copilot#logger#BufReadCmd() abort
try
setlocal modifiable noreadonly
silent call deletebufline('', 1, '$')
if !empty(s:logs)
call setline(1, s:logs)
endif
finally
setlocal buftype=nofile bufhidden=wipe nobuflisted nomodified nomodifiable
endtry
endfunction
let s:level_prefixes = ['', '[ERROR] ', '[WARN] ', '[INFO] ', '[DEBUG] ', '[DEBUG] ']
function! copilot#logger#Raw(level, message) abort
let lines = type(a:message) == v:t_list ? copy(a:message) : split(a:message, "\n", 1)
let lines[0] = strftime('[%Y-%m-%d %H:%M:%S] ') . get(s:level_prefixes, a:level, '[UNKNOWN] ') . get(lines, 0, '')
try
if !filewritable(s:log_file)
return
endif
call map(lines, { k, L -> type(L) == v:t_func ? call(L, []) : L })
call extend(s:logs, lines)
let overflow = len(s:logs) - get(g:, 'copilot_log_history', 10000)
if overflow > 0
call remove(s:logs, 0, overflow - 1)
endif
let bufnr = bufnr('copilot:///log')
if bufnr > 0 && bufloaded(bufnr)
call setbufvar(bufnr, '&modifiable', 1)
call setbufline(bufnr, 1, s:logs)
call setbufvar(bufnr, '&modifiable', 0)
for winid in win_findbuf(bufnr)
if has('nvim') && winid != win_getid()
call nvim_win_set_cursor(winid, [len(s:logs), 0])
endif
endfor
endif
catch
endtry
endfunction
function! copilot#logger#Debug(...) abort
if empty(get(g:, 'copilot_debug'))
return
endif
call copilot#logger#Raw(4, a:000)
endfunction
function! copilot#logger#Info(...) abort
call copilot#logger#Raw(3, a:000)
endfunction
function! copilot#logger#Warn(...) abort
call copilot#logger#Raw(2, a:000)
endfunction
function! copilot#logger#Error(...) abort
call copilot#logger#Raw(1, a:000)
endfunction
function! copilot#logger#Bare(...) abort
call copilot#logger#Raw(0, a:000)
endfunction
function! copilot#logger#Exception(...) abort
if !empty(v:exception) && v:exception !=# 'Vim:Interrupt'
call copilot#logger#Error('Exception: ' . v:exception . ' @ ' . v:throwpoint)
let client = copilot#RunningClient()
if !empty(client)
let [_, type, code, message; __] = matchlist(v:exception, '^\%(\(^[[:alnum:]_#]\+\)\%((\a\+)\)\=\%(\(:E-\=\d\+\)\)\=:\s*\)\=\(.*\)$')
let stacklines = []
for frame in split(substitute(v:throwpoint, ', \S\+ \(\d\+\)$', '[\1]', ''), '\.\@<!\.\.\.\@!')
let fn_line = matchlist(frame, '^\%(function \)\=\(\S\+\)\[\(\d\+\)\]$')
if !empty(fn_line)
call add(stacklines, {'function': substitute(fn_line[1], '^<SNR>\d\+_', '<SID>', ''), 'lineno': +fn_line[2]})
elseif frame =~# ' Autocmds for "\*"$'
call add(stacklines, {'function': frame})
elseif frame =~# ' Autocmds for ".*"$'
call add(stacklines, {'function': substitute(frame, ' for ".*"$', ' for "[redacted]"', '')})
else
call add(stacklines, {'function': '[redacted]'})
endif
endfor
return client.Request('telemetry/exception', {
\ 'transaction': a:0 ? a:1 : '',
\ 'platform': 'other',
\ 'exception_detail': [{
\ 'type': type . code,
\ 'value': message,
\ 'stacktrace': stacklines}]
\ }, v:null, function('copilot#util#Nop'))
endif
endif
endfunction

View File

@@ -1,167 +0,0 @@
scriptencoding utf-8
if !exists('s:panel_id')
let s:panel_id = 0
endif
let s:separator = repeat('─', 72)
function! s:Render(state) abort
let bufnr = bufnr('^' . a:state.panel . '$')
let state = a:state
if !bufloaded(bufnr)
return
endif
let sorted = a:state.items
if !empty(get(a:state, 'error'))
let lines = ['Error: ' . a:state.error.message]
let sorted = []
elseif get(a:state, 'percentage') == 100
let lines = ['Synthesized ' . (len(sorted) == 1 ? '1 completion' : len(sorted) . ' completions')]
else
let lines = [substitute('Synthesizing ' . matchstr(get(a:state, 'message', ''), '\d\+\%(/\d\+\)\=') . ' completions', ' \+', ' ', 'g')]
endif
if len(sorted)
call add(lines, 'Press <CR> on a completion to accept')
endif
let leads = {}
for item in sorted
let insert = split(item.insertText, "\r\n\\=\\|\n", 1)
let insert[0] = strpart(a:state.line, 0, copilot#util#UTF16ToByteIdx(a:state.line, item.range.start.character)) . insert[0]
let lines += [s:separator] + insert
if !has_key(leads, string(item.range.start))
let match = insert[0 : a:state.position.line - item.range.start.line]
let match[-1] = strpart(match[-1], 0, copilot#util#UTF16ToByteIdx(match[-1], a:state.position.character))
call map(match, { k, v -> escape(v, '][^$.*\~') })
let leads[string(item.range.start)] = join(match, '\n')
endif
endfor
try
call setbufvar(bufnr, '&modifiable', 1)
call setbufvar(bufnr, '&readonly', 0)
call setbufline(bufnr, 1, lines)
finally
call setbufvar(bufnr, '&modifiable', 0)
endtry
call clearmatches()
call matchadd('CopilotSuggestion', '\C^' . s:separator . '\n\zs\%(' . join(sort(values(leads), { a, b -> len(b) - len(a) }), '\|') . '\)', 10, 4)
endfunction
function! s:PartialResult(state, value) abort
let items = type(a:value) == v:t_list ? a:value : a:value.items
call extend(a:state.items, items)
call s:Render(a:state)
endfunction
function! s:WorkDone(state, value) abort
if has_key(a:value, 'message')
let a:state.message = a:value.message
endif
if has_key(a:value, 'percentage')
let a:state.percentage = a:value.percentage
call s:Render(a:state)
endif
endfunction
function! copilot#panel#Accept(...) abort
let state = get(b:, 'copilot_panel', {})
if empty(state.items)
return ''
endif
if !has_key(state, 'bufnr') || !bufloaded(get(state, 'bufnr', -1))
return "echoerr 'Buffer was closed'"
endif
let at = a:0 ? a:1 : line('.')
let index = 0
for lnum in range(1, at)
if getline(lnum) ==# s:separator
let index += 1
endif
endfor
if index > 0 && index <= len(state.items)
let item = state.items[index - 1]
let lnum = item.range.start.line + 1
if getbufline(state.bufnr, lnum) !=# [state.line]
return 'echoerr "Buffer has changed since synthesizing completion"'
endif
let lines = split(item.insertText, "\n", 1)
let old_first = getbufline(state.bufnr, item.range.start.line + 1)[0]
let lines[0] = strpart(old_first, 0, copilot#util#UTF16ToByteIdx(old_first, item.range.start.character)) . lines[0]
let old_last = getbufline(state.bufnr, item.range.end.line + 1)[0]
let lines[-1] .= strpart(old_last, copilot#util#UTF16ToByteIdx(old_last, item.range.end.character))
call deletebufline(state.bufnr, item.range.start.line + 1, item.range.end.line + 1)
call appendbufline(state.bufnr, item.range.start.line, lines)
call copilot#Request('workspace/executeCommand', item.command)
bwipeout
let win = bufwinnr(state.bufnr)
if win > 0
exe win . 'wincmd w'
exe item.range.start.line + len(lines)
if state.was_insert
startinsert!
else
normal! $
endif
endif
endif
return ''
endfunction
function! s:Initialize(state) abort
let &l:filetype = 'copilot' . (empty(a:state.filetype) ? '' : '.' . a:state.filetype)
let &l:tabstop = a:state.tabstop
nmap <buffer><script> <CR> <Cmd>exe copilot#panel#Accept()<CR>
nmap <buffer><script> [[ <Cmd>call search('^─\{9,}\n.', 'bWe')<CR>
nmap <buffer><script> ]] <Cmd>call search('^─\{9,}\n.', 'We')<CR>
endfunction
function! s:BufReadCmd() abort
setlocal bufhidden=wipe buftype=nofile nobuflisted nomodifiable
let state = get(b:, 'copilot_panel')
if type(state) != v:t_dict
return
endif
call s:Initialize(state)
call s:Render(state)
return ''
endfunction
function! s:Result(state, result) abort
let a:state.percentage = 100
call s:PartialResult(a:state, a:result)
endfunction
function! s:Error(state, error) abort
let a:state.error = a:error
call s:Render(a:state)
endfunction
function! copilot#panel#Open(opts) abort
let s:panel_id += 1
let state = {'items': [], 'filetype': &filetype, 'was_insert': mode() =~# '^[iR]', 'bufnr': bufnr(''), 'tabstop': &tabstop}
let state.panel = 'copilot:///panel/' . s:panel_id
if state.was_insert
let state.position = copilot#util#AppendPosition()
stopinsert
else
let state.position = {'line': a:opts.line1 >= 1 ? a:opts.line1 - 1 : 0, 'character': copilot#util#UTF16Width(getline('.'))}
endif
let state.line = getline(state.position.line + 1)
let params = {
\ 'textDocument': {'uri': state.bufnr},
\ 'position': state.position,
\ 'partialResultToken': function('s:PartialResult', [state]),
\ 'workDoneToken': function('s:WorkDone', [state]),
\ }
let response = copilot#Request('textDocument/copilotPanelCompletion', params, function('s:Result', [state]), function('s:Error', [state]))
exe substitute(a:opts.mods, '\C\<tab\>', '-tab', 'g') 'keepalt split' state.panel
let b:copilot_panel = state
call s:Initialize(state)
call s:Render(state)
return ''
endfunction
augroup github_copilot_panel
autocmd!
autocmd BufReadCmd copilot:///panel/* exe s:BufReadCmd()
augroup END

View File

@@ -1,61 +0,0 @@
let s:deferred = []
function! copilot#util#Nop(...) abort
return v:null
endfunction
function! copilot#util#Defer(fn, ...) abort
call add(s:deferred, function(a:fn, a:000))
return timer_start(0, function('s:RunDeferred'))
endfunction
function! s:RunDeferred(...) abort
if empty(s:deferred)
return
endif
let Fn = remove(s:deferred, 0)
call timer_start(0, function('s:RunDeferred'))
call call(Fn, [])
endfunction
function! copilot#util#UTF16Width(str) abort
return strchars(substitute(a:str, "\\%#=2[^\u0001-\uffff]", " ", 'g'))
endfunction
if exists('*utf16idx')
function! copilot#util#UTF16ToByteIdx(str, utf16_idx) abort
return byteidx(a:str, a:utf16_idx, 1)
endfunction
elseif has('nvim')
function! copilot#util#UTF16ToByteIdx(str, utf16_idx) abort
try
return v:lua.vim.str_byteindex(a:str, a:utf16_idx, 1)
catch /^Vim(return):E5108:/
return -1
endtry
endfunction
else
function! copilot#util#UTF16ToByteIdx(str, utf16_idx) abort
if copilot#util#UTF16Width(a:str) < a:utf16_idx
return -1
endif
let end_offset = len(a:str)
while copilot#util#UTF16Width(strpart(a:str, 0, end_offset)) > a:utf16_idx && end_offset > 0
let end_offset -= 1
endwhile
return end_offset
endfunction
endif
function! copilot#util#AppendPosition() abort
let line = getline('.')
let col_byte = col('.') - (mode() =~# '^[iR]' || empty(line))
let col_utf16 = copilot#util#UTF16Width(strpart(line, 0, col_byte))
return {'line': line('.') - 1, 'character': col_utf16}
endfunction

View File

@@ -1,3 +0,0 @@
function! copilot#version#String() abort
return '1.41.0'
endfunction

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More