⚡ move ~/bin to ~/.local/bin
This commit is contained in:
1
.bashrc
1
.bashrc
@@ -12,7 +12,6 @@ shopt -s expand_aliases
|
|||||||
[ -f $BASH_DOTFILES/.bash_sdkman ] && . $BASH_DOTFILES/.bash_sdkman
|
[ -f $BASH_DOTFILES/.bash_sdkman ] && . $BASH_DOTFILES/.bash_sdkman
|
||||||
[ -f $BASH_DOTFILES/.bash_nvm ] && . $BASH_DOTFILES/.bash_nvm
|
[ -f $BASH_DOTFILES/.bash_nvm ] && . $BASH_DOTFILES/.bash_nvm
|
||||||
export NODE_COMPILE_CACHE=~/.cache/nodejs-compile-cache # https://nolanlawson.com/2024/10/20/why-im-skeptical-of-rewriting-javascript-tools-in-faster-languages/
|
export NODE_COMPILE_CACHE=~/.cache/nodejs-compile-cache # https://nolanlawson.com/2024/10/20/why-im-skeptical-of-rewriting-javascript-tools-in-faster-languages/
|
||||||
export PATH="$HOME/.local/bin:$PATH"
|
|
||||||
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
|
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
|
||||||
[ -f $BASH_DOTFILES/.bash_completions ] && . $BASH_DOTFILES/.bash_completions # for Vim
|
[ -f $BASH_DOTFILES/.bash_completions ] && . $BASH_DOTFILES/.bash_completions # for Vim
|
||||||
|
|
||||||
|
@@ -148,9 +148,9 @@
|
|||||||
"group": "ai",
|
"group": "ai",
|
||||||
"file_name": "ollama",
|
"file_name": "ollama",
|
||||||
"exec": "yes",
|
"exec": "yes",
|
||||||
"last_update": "2025-08-25T18:04:05Z",
|
"last_update": "2025-09-04T17:27:40Z",
|
||||||
"downloads": "/home/jaandrle/bin/ollama",
|
"downloads": "/home/jaandrle/bin/ollama",
|
||||||
"version": "v0.11.7",
|
"version": "v0.11.10",
|
||||||
"glare": "linux-amd64"
|
"glare": "linux-amd64"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -173,8 +173,8 @@
|
|||||||
"file_name": "vim",
|
"file_name": "vim",
|
||||||
"exec": "yes",
|
"exec": "yes",
|
||||||
"downloads": "/home/jaandrle/bin/vim",
|
"downloads": "/home/jaandrle/bin/vim",
|
||||||
"version": "v9.1.1696",
|
"version": "v9.1.1744",
|
||||||
"last_update": "2025-08-27T01:22:07Z",
|
"last_update": "2025-09-09T01:22:24Z",
|
||||||
"glare": "GVim.*x86_64.*.AppImage"
|
"glare": "GVim.*x86_64.*.AppImage"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -184,9 +184,9 @@
|
|||||||
"group": "dev",
|
"group": "dev",
|
||||||
"file_name": "escrcpy.appimage",
|
"file_name": "escrcpy.appimage",
|
||||||
"exec": "yes",
|
"exec": "yes",
|
||||||
"last_update": "2025-07-15T10:25:01Z",
|
"last_update": "2025-09-08T03:15:03Z",
|
||||||
"downloads": "/home/jaandrle/bin/escrcpy.appimage",
|
"downloads": "/home/jaandrle/bin/escrcpy.appimage",
|
||||||
"version": "v1.30.2",
|
"version": "v1.32.0",
|
||||||
"glare": ".*x86_64.*.AppImage"
|
"glare": ".*x86_64.*.AppImage"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -208,9 +208,9 @@
|
|||||||
"group": "ai",
|
"group": "ai",
|
||||||
"file_name": "jan",
|
"file_name": "jan",
|
||||||
"exec": "yes",
|
"exec": "yes",
|
||||||
"last_update": "2025-08-14T09:29:09Z",
|
"last_update": "2025-08-28T10:22:10Z",
|
||||||
"downloads": "/home/jaandrle/bin/jan",
|
"downloads": "/home/jaandrle/bin/jan",
|
||||||
"version": "v0.6.8",
|
"version": "v0.6.9",
|
||||||
"glare": ".*x86_64.*.AppImage"
|
"glare": ".*x86_64.*.AppImage"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
3
.local/bin/kde6-workarounds.sh
Executable file
3
.local/bin/kde6-workarounds.sh
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -eou pipefail
|
||||||
|
dbus-monitor "interface=org.kde.KWin.VirtualDesktopManager" "member=currentChanged" | xargs -e -I {} kde6-workarounds.mjs desktops-last-save {}
|
1
.local/bin/ra-aid
Symbolic link
1
.local/bin/ra-aid
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
/home/jaandrle/.local/share/pipx/venvs/ra-aid/bin/ra-aid
|
8
.local/bin/§openai
Executable file
8
.local/bin/§openai
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
curl \
|
||||||
|
-sSL \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-H 'Authorization: Bearer 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 ' \
|
||||||
|
-d '{"prompt":"//'"$1"'","max_tokens":500,"stop":"//","n":3}' \
|
||||||
|
https://api.openai.com/v1/engines/code-davinci-002/completions
|
131
.local/bin/§pandoc.mjs
Executable file
131
.local/bin/§pandoc.mjs
Executable file
@@ -0,0 +1,131 @@
|
|||||||
|
#!/usr/bin/env nodejsscript
|
||||||
|
/* jshint esversion: 11,-W097, -W040, module: true, node: true, expr: true, undef: true *//* global echo, $, pipe, s, fetch, cyclicLoop */
|
||||||
|
if(!s.which("pandoc")) throw new Error("pandoc not found. Use your package manager to install it (e.g. `sudo apt install pandoc`).");
|
||||||
|
const pdftk= "§pdftk-data.mjs";
|
||||||
|
if(!s.which(pdftk)) throw new Error(`${pdftk} user script not found.`);
|
||||||
|
|
||||||
|
$.api()
|
||||||
|
.version("2025-09-04")
|
||||||
|
.describe([
|
||||||
|
"Small wrapper around `pandoc` mainly to convert markdown to pdf.",
|
||||||
|
"The reason is to use modern CSS than rely on cli implementation to converting to pdf."
|
||||||
|
])
|
||||||
|
.option("--debug", "Debug mode")
|
||||||
|
.option("--force", "Overwrite output file.")
|
||||||
|
|
||||||
|
.command("to-html <name-input> [name-output]", "Convert markdown to html.")
|
||||||
|
.alias("tohtml")
|
||||||
|
.action(function tohtmlCMD(input, output, options){
|
||||||
|
tohtml(input, output, options);
|
||||||
|
$.exit(0);
|
||||||
|
})
|
||||||
|
|
||||||
|
.command("to-pdf <name-input> [name-output]", "Convert markdown to pdf.")
|
||||||
|
.alias("topdf")
|
||||||
|
.action(async function topdfCMD(input, output, options){
|
||||||
|
const { force: isForced, debug: isDebug }= options;
|
||||||
|
testInput(input);
|
||||||
|
output= normalizeOutput(input, ".pdf", output, isForced);
|
||||||
|
const tempFile= tempFileGenerator(input);
|
||||||
|
|
||||||
|
echo("1. step: convert to html");
|
||||||
|
const output_html= tempFile(".html");
|
||||||
|
const input_data= tohtml(input, output_html, options);
|
||||||
|
|
||||||
|
echo("2. step: convert to pdf");
|
||||||
|
echo(" …use print to pdf in your browser");
|
||||||
|
s.run`open ${output_html}`;
|
||||||
|
await s.read({ "-p": "Press enter to continue" }).catch(()=> echo("Aborted"));
|
||||||
|
if(!isDebug) s.rm(output_html);
|
||||||
|
if(!s.test("-f", output))
|
||||||
|
$.error("Output file not found");
|
||||||
|
|
||||||
|
echo("3. step: update pdf metadata");
|
||||||
|
const output_data_file= tempFile(".json");
|
||||||
|
echo(` ${pdftk} extract \${pdf}`);
|
||||||
|
s.run`${pdftk} extract ${output} ${output_data_file}`;
|
||||||
|
const output_data= s.cat(output_data_file).xargs(JSON.parse);
|
||||||
|
const { Creator }= output_data.Info;
|
||||||
|
input_data.Creator= [
|
||||||
|
s.$().run`pandoc --version`.head({ "-n": 1 }).trim(),
|
||||||
|
"&",
|
||||||
|
Creator,
|
||||||
|
].join(" ");
|
||||||
|
Object.assign(output_data.Info, input_data);
|
||||||
|
s.echo(JSON.stringify(output_data, null, "\t")).to(output_data_file);
|
||||||
|
echo(` ${pdftk} update \${pdf}`);
|
||||||
|
s.run`${pdftk} update ${output} ${output_data_file}`;
|
||||||
|
if(!isDebug) s.rm(output_data_file);
|
||||||
|
|
||||||
|
$.exit(0);
|
||||||
|
})
|
||||||
|
.parse();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {string} [output]
|
||||||
|
* @param {object} options
|
||||||
|
* @returns {Record<string, string>}
|
||||||
|
* */
|
||||||
|
function tohtml(
|
||||||
|
input, output,
|
||||||
|
{ force: isForced, debug: isDebug }
|
||||||
|
){
|
||||||
|
testInput(input);
|
||||||
|
output= normalizeOutput(input, ".html", output, isForced);
|
||||||
|
const tempFile= tempFileGenerator(input);
|
||||||
|
|
||||||
|
const { input_tmp, input_data }= prepareInput(input, tempFile);
|
||||||
|
echo(" pandoc ${markdown} --standalone -o ${html}");
|
||||||
|
s.run`pandoc ${input_tmp} --standalone -o ${output}`;
|
||||||
|
if(!isDebug) s.rm(input_tmp);
|
||||||
|
return input_data;
|
||||||
|
}
|
||||||
|
/** @param {string} orig */
|
||||||
|
function tempFileGenerator(orig){
|
||||||
|
const basepath= orig.includes("/") ? orig.slice(0, orig.lastIndexOf("/")+1) : "";
|
||||||
|
const basename= orig.slice(basepath.length, orig.lastIndexOf("."));
|
||||||
|
return ext=> basepath+"."+basename+"-"+nameHash()+ext;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {(ext: string)=> string} tempFile
|
||||||
|
* @returns {{ input_tmp: string, input_data: Record<string, string> }}
|
||||||
|
* */
|
||||||
|
function prepareInput(input, tempFile){
|
||||||
|
const input_tmp= tempFile(".md");
|
||||||
|
const content= s.cat(input).trim();
|
||||||
|
let input_data= {};
|
||||||
|
echo(" extract input metadata and eval `~` to $HOME (CSS)");
|
||||||
|
if(content.startsWith("---"))
|
||||||
|
for(const line_raw of content.split("\n").slice(1)){
|
||||||
|
const line= line_raw.trim();
|
||||||
|
if(!line) continue;
|
||||||
|
if(line==="---") break;
|
||||||
|
const [key_raw, value]= line.split(/: */);
|
||||||
|
let key= key_raw.replace(/^-+/, "");
|
||||||
|
key= key[0].toUpperCase()+key.slice(1);
|
||||||
|
input_data[key]= value;
|
||||||
|
}
|
||||||
|
s.echo(content.replaceAll("file:///~", "file:///"+process.env.HOME)).to(input_tmp);
|
||||||
|
return { input_tmp, input_data };
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param {string} input Input file
|
||||||
|
* @param {string} ext Output file extension
|
||||||
|
* @param {string} [output] Output file
|
||||||
|
* @param {boolean} [isForced] Overwrite output file
|
||||||
|
* @returns {string}
|
||||||
|
* @throws {Error} When output file already exists (unless `--force`)
|
||||||
|
* */
|
||||||
|
function normalizeOutput(input, ext, output, isForced){
|
||||||
|
if(!output) output= input.slice(0, input.lastIndexOf("."))+ext;
|
||||||
|
if(s.test("-f", output)) {
|
||||||
|
if(!isForced) $.error("Output file already exists, choose another name or `--force`");
|
||||||
|
s.rm(output);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
/** @param {string} input @throws {Error} If input file not found */
|
||||||
|
function testInput(input){ if(!s.test("-f", input)) $.error("Input file not found"); }
|
||||||
|
function nameHash(){ return Math.random().toString(36).slice(2); }
|
@@ -12,14 +12,11 @@ $.api()
|
|||||||
])
|
])
|
||||||
.option("--debug", "Debug mode")
|
.option("--debug", "Debug mode")
|
||||||
.command("extract <file_pdf> [file_info]", "Extract data from PDF.")
|
.command("extract <file_pdf> [file_info]", "Extract data from PDF.")
|
||||||
.action(function extract(file_pdf, file_info, { debug }){
|
.action(function extractCMD(file_pdf, file_info, { debug }){
|
||||||
if(!s.test("-f", file_pdf)) $.error("PDF File not found");
|
if(!s.test("-f", file_pdf)) $.error("PDF File not found");
|
||||||
if(!file_info) file_info= filename(file_pdf) + ".json";
|
if(!file_info) file_info= filename(file_pdf) + ".json";
|
||||||
|
|
||||||
const temp= `${tmp}${tmpname(file_pdf)}.info` ;
|
const info= extract(file_pdf);
|
||||||
s.run`pdftk ${file_pdf} dump_data_utf8 output ${temp}`;
|
|
||||||
const info= infoToJSON(temp);
|
|
||||||
if(!debug) s.rm(temp);
|
|
||||||
s.echo(info).to(file_info);
|
s.echo(info).to(file_info);
|
||||||
$.exit(0);
|
$.exit(0);
|
||||||
})
|
})
|
||||||
@@ -28,8 +25,10 @@ $.api()
|
|||||||
if(!s.test("-f", file_pdf)) $.error("PDF File not found");
|
if(!s.test("-f", file_pdf)) $.error("PDF File not found");
|
||||||
if(!file_info) file_info= filename(file_pdf) + ".json";
|
if(!file_info) file_info= filename(file_pdf) + ".json";
|
||||||
if(!s.test("-f", file_info)) $.error("Info File not found");
|
if(!s.test("-f", file_info)) $.error("Info File not found");
|
||||||
|
|
||||||
|
const infoIsHtml= file_info.endsWith(".html");
|
||||||
|
|
||||||
const info= infoFromJSON(file_info);
|
const info= infoIsHtml ? infoFromHTML(file_info, file_pdf, debug) : infoFromJSON(file_info);
|
||||||
const temp= `${tmp}${tmpname(file_pdf)}.info`;
|
const temp= `${tmp}${tmpname(file_pdf)}.info`;
|
||||||
s.echo(info).to(temp);
|
s.echo(info).to(temp);
|
||||||
const tmp_pdf= `${tmp}${tmpname(file_pdf)}.pdf`;
|
const tmp_pdf= `${tmp}${tmpname(file_pdf)}.pdf`;
|
||||||
@@ -51,13 +50,52 @@ $.api()
|
|||||||
})
|
})
|
||||||
.parse();
|
.parse();
|
||||||
|
|
||||||
|
function extract(file_pdf, debug){
|
||||||
|
const temp= `${tmp}${tmpname(file_pdf)}.info` ;
|
||||||
|
s.run`pdftk ${file_pdf} dump_data_utf8 output ${temp}`;
|
||||||
|
const out= infoToJSON(temp);
|
||||||
|
if(!debug) s.rm(temp);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
function filename(path){ return path.slice(path.lastIndexOf("/")+1, path.lastIndexOf(".")); }
|
function filename(path){ return path.slice(path.lastIndexOf("/")+1, path.lastIndexOf(".")); }
|
||||||
function tmpname(path){ return filename(path) + "-" + Date.now(); }
|
function tmpname(path){ return filename(path) + "-" + Date.now(); }
|
||||||
|
function infoFromHTML(file_info, file_pdf, debug){
|
||||||
|
const info_orig= JSON.parse(extract(file_pdf, debug));
|
||||||
|
const info= s.cat(file_info).trim();
|
||||||
|
let isInside= false;
|
||||||
|
for(const line_raw of info.split("\n")){
|
||||||
|
const line= line_raw.trim();
|
||||||
|
if(line.startsWith("<head")){
|
||||||
|
isInside= true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(!line || !isInside) continue;
|
||||||
|
if(line.startsWith("<title>")){
|
||||||
|
const title= line.slice(7).replace("</title>", "").trim();
|
||||||
|
info_orig.Info.Title= title;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(line.startsWith("<meta") && line.includes("name=")){
|
||||||
|
const [,, key]= line.match(/name=("|')(.*?)(\1)/);
|
||||||
|
const [,, value]= line.match(/content=("|')(.*?)(\1)/);
|
||||||
|
info_orig.Info[key[0].toUpperCase()+key.slice(1)]= value;
|
||||||
|
}
|
||||||
|
if(line.startsWith("</head>")){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const tmp_json= `${tmp}${tmpname(file_pdf)}.json`;
|
||||||
|
s.echo(JSON.stringify(info_orig, null, "\t")).to(tmp_json);
|
||||||
|
const out= infoFromJSON(tmp_json);
|
||||||
|
if(!debug) s.rm(tmp_json);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
function infoFromJSON(file_info){
|
function infoFromJSON(file_info){
|
||||||
const info= s.cat(file_info).xargs(JSON.parse);
|
const info= s.cat(file_info).xargs(JSON.parse);
|
||||||
const output= [];
|
const output= [];
|
||||||
info.Bookmark= Object.entries(info.Bookmark)
|
info.Bookmark= Object.entries(info.Bookmark)
|
||||||
.map(/** @param {[string, string]} _ */([PageNumber, Title])=> {
|
.map(/** @param {[string, string]} _ */([PageNumber, Title])=> {
|
||||||
|
PageNumber= Number.parseInt(PageNumber);
|
||||||
const level= Title.search(/[^ ]/);
|
const level= Title.search(/[^ ]/);
|
||||||
return {
|
return {
|
||||||
PageNumber,
|
PageNumber,
|
||||||
@@ -134,7 +172,7 @@ function infoToJSON(file_info){
|
|||||||
output.set(key, value);
|
output.set(key, value);
|
||||||
}
|
}
|
||||||
output.set("Bookmark", pipe(
|
output.set("Bookmark", pipe(
|
||||||
items=> items.map(({ PageNumber, Title, Level })=> ([PageNumber, " ".repeat(Number(Level)-1) + Title])),
|
items=> items.map(({ PageNumber, Title, Level }, i)=> ([PageNumber+"-"+i, " ".repeat(Number(Level)-1) + Title])),
|
||||||
Object.fromEntries,
|
Object.fromEntries,
|
||||||
)(output.get("Bookmark") || []));
|
)(output.get("Bookmark") || []));
|
||||||
return pipe(
|
return pipe(
|
2
.local/bin/§§centrum_mail
Executable file
2
.local/bin/§§centrum_mail
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
kioclient5 exec https://mail.centrum.cz/?fld=-666
|
@@ -21,7 +21,7 @@ see for example [How to Store Dotfiles - A Bare Git Repository \| Atlassian Git
|
|||||||
- [git](./.config/git/config), [gh](./.config/gh/config.yml)
|
- [git](./.config/git/config), [gh](./.config/gh/config.yml)
|
||||||
- [KDE Neon](#kde-neon)
|
- [KDE Neon](#kde-neon)
|
||||||
- [Mozilla Firefox](./.mozilla/firefox/README.md)
|
- [Mozilla Firefox](./.mozilla/firefox/README.md)
|
||||||
- [Bin – scripts and executables](./bin/README.md)
|
- [Bin – scripts and executables](./.local/bin/README.md)
|
||||||
|
|
||||||
## On a new machine
|
## On a new machine
|
||||||
1. install git
|
1. install git
|
||||||
|
Reference in New Issue
Block a user