Migrate from dotfiles to full nix config.

See voronind/linux for history.
This commit is contained in:
Dmitry Voronin 2024-03-04 00:34:39 +03:00
commit 47a6c9537f
201 changed files with 8371 additions and 0 deletions

452
.doc/Bash.md Normal file
View file

@ -0,0 +1,452 @@
# Bash reference file.
To get help with usage info run:
```text
$ help <COMMAND>
or
$ h <COMMAND>
```
## Android.
Command|Description
---|---
`emulator [NAME]`|Start an Android emulator. Default name is `main`.
## Archive.
Command|Description
---|---
`archive [DIRS]`|Archive directories. All directories by default. Supports .archiveignore exclude file.
`archive_mt [DIRS]`|Archive using multiple threads. Uses 75% of free RAM. All directories by default. Supports .archiveignore exclude file.
`archive_fast [DIRS]`|Archive directories with fast compression. All directories by default. Supports .archiveignore exclude file.
`archive_check [FILES]`|Check archives integrity. Checks all archives by default.
`archive_prune [NAME] [VERSIONS]`|Delete old versions of an archive. All archives with 1 version by default.
`archive_rm [FILES]`|Delete specified or all archive files.
`archive_xz [FILES]`|Recompress previously created archive_fast with better compression.
`archive_name [ARCHIVE] [NAME]`|Rename archives. If no name specified, it simplifies archive's name. If no archives specified, apply to all archives.
`unarchive [FILES]`|Extract previously created archive with checksum validation.
`archive_touch [FILES]`|Change archive's filesystem time to match creation date.
## Ask.
Command|Description
---|---
`ask <QUERY>`|Ask general AI.
`ask_code <QUERY>`|Ask code AI.
## Battery.
Command|Description
---|---
`battery_charge`| Print current battery charge in percents.
`battery_info`| Get battery's info.
## Bootstrap.
Command|Description
---|---
`bootstrap_editorconfig`| Install Editorconfig file (with tabs) in current directory.
`bootstrap_editorconfig_space [AMOUNT]`|Install Editorconfig file (with specified spaces, 8 by default) in current directory.
`bootstrap_nixos <DRIVE> [HOST]`|Install nixos to specified drive. To be run from Live ISO.
## Cd.
Command|Description
---|---
`cdd <DIR>`|CD (back to) directory. Goes to the exact-match dir first. If no exact match found, it finds first directory that contains the input (case-insensitive).
## Checksum.
Command|Description
---|---
`checksum_create [FILES]`|Save file checksums. For file with a name `file` it will create a new file called `.file.sha1` with hash in it. All files by default.
`checksum_check [FILES]`|Check stored values against actual files. All files by default.
`checksum`| Calculate hashes for all files recursively and store in a file called `checksum.sha1`.
## Chmod.
Command|Description
---|---
`x <FILES>`|Add executable flag to file.
## Color.
Command|Description
---|---
`color_test`| Print all available colors with their names colored in corresponding color.
## Container.
Command|Description
---|---
`ca [NAME]`|Attach/create container box in current directory with specified name. By default uses current dir name.
`ck [NAME]`|Remove container box with specified name. By default uses current dir name.
`cka`| Remove all container boxes.
`cl`| List all container boxes.
## Copypaste.
Command|Description
---|---
`copy`| Copy stdin to system clipboard. *Example:* `echo hi \| copy`.
`paste`| Paste system clipboard to stdout. *Example:* `paste > file.txt`.
## Cp.
Command|Description
---|---
`rcp <FROM> <TO>`|Replaces default cp with rsync.
`rcp_merge <FROM> <TO>`|Copy and also merge all changes (delete dst files that do not exist in src).
`cp_link <FROM> <TO>`|Copy by creating hardlinks. Works for directories, too.
`rcp_test <FROM> <TO>`|Print output of cp_merge without writing anything.
## Date.
Command|Description
---|---
`today`| Print today date in yyyyMMdd format.
`dow`| Current day of week number.
## Dconf.
Command|Description
---|---
`dconf_load`| Load Gnome settings.
`dconf_save [FILE]`|Dump Gnome settings into the file. Default name is `gnome.dconf`. Do this before changing settings and after, an then run `diff` to find out what to add to the main `gnome.dconf`.
## Disk.
Command|Description
---|---
`pdf`| Show only physical drives info.
`tdu [DIRS]`|Show total size in SI. Current dir by default.
## Distrobox.
Command|Description
---|---
`da [BOX]`|Create/Attach to the box. Uses name `main` by default.
## Docker.
Command|Description
---|---
`docker_volumes <CONTAINER>`|Show container's volumes.
`docker_health`| Check if any container exited.
`docker_ip <CONTAINER>`|Find out container's IP address.
`docker_update`| Update all docker images.
`dc`| Docker compose shortcut.
`dcu [SERVICES]`|Docker compose up.
`dcd [SERVICES]`|Docker compose down.
`dcp [SERVICES]`|Docker compose pull.
`dcl [SERVICES]`|Docker compose logs.
`dcr [SERVICES]`|Docker compose restart.
`dcs [SERVICES]`|Docker compose stop.
`dcdu [SERVICES]`|Docker compose down & up specified services.
`dcpu [SERVICES]`|Docker compose pull & up specified services.
`dcul [SERVICES]`|Docker compose up & attach to logs for specified services.
## Doc.
Command|Description
---|---
`doc_bash`|Generate a markdown file with all the help info. Outputs to `~/.doc/Bash.md`.
## Dvd.
Command|Description
---|---
`dvd_burn_iso <FILE.iso>`|Burn specified iso file to DVD.
`cd_burn_iso <FILE.iso>`|Burn specified iso file to CD.
`cd_burn_audio <FILES.wav>`|Burn specified audio files to CD.
`dvd_shell`| Spawn Nix shell with required tools.
## Ffmpeg.
Command|Description
---|---
`ffmpeg_mux_audio <SOUND> <OUTPUT DIR>`|Mux audio into containers. File names in sound and current dirrectories must match.
`ffmpeg_mux_cover <FORMAT> <COVER>`|Mux cover into music file.
`ffmpeg_music_meta <FORMAT>`|Generate music metadata from directory structure. Top dir is the Artist name like this: `The_Beatles`. Next are albums like this: `2010_My_love`. Inside are songs like this: `01_sample.flac`.
## File.
Command|Description
---|---
`o <FILE>`|Open file/dir in GUI.
`play [FILE]`|Play media file from CLI. All files by default.
`play_shuffle [FILE]`|Play media files shuffled from CLI. All files by default.
## Find.
Command|Description
---|---
`find_ext`| Find all file extensions.
`find_module`| Find all modules.
`find_function [MODULE]`|Find all module functions. Functions from all modules by default.
## Fix.
Command|Description
---|---
`fix_ethernet_speed <DEVICE> <SPEED>`|Fix when ethernet mistakenly detects 100 Mb instead of 1000 Mb. SPEED is one of 10/100/1000 etc.
`fix_files_sftp`| Fix nautilus after typing wrong sftp password.
`fix_gradle_lock`| Delete lost Gradle lock files.
`fix_gnome_rdp <PASSWORD>`|Fix Gnome's broken RDP ffs.
## Git.
Command|Description
---|---
`gps`| Git push.
`gpsa`| Git push all (branches). Useful for pushing all stuff to a new remote.
`gpsf`| Git force push.
`gpl`| Git pull.
`gl`| Git log.
`gs`| Git status.
`gst`| Git stash.
`gd`| Git diff.
`gc`| Git commit.
`gch`| Git checkout.
`gchb <BRANCH>`|Git checkout branch.
`gb`| Git branch.
`gbd <BRANCH>`|Git branch delete.
`gbda`| Git branch delete all except current.
`gf`| Git fetch all.
`gt`| Git tag.
`gi`| Git ignore files.
`gpc <FILE>`|Git patch create.
`gp <FILE>`|Git patch (apply).
`ggc`| Run git garbage collection.
`ga [FILES]`|Preview diff while adding. Adds current dir by default.
`gr [COMMIT COUNT]`|Rebase by X commits or from root. When COUNT is 0 - rebase from root. Default is 2.
`gu [EMAIL]`|Specify git user as Dmitry Voronin with provided email.
`gg <REPO>`|Get my git repo.
`gdc [COMMITHASH]`|See diff for a specific commit. Last commit by default.
`gv`| Get version number based on commit count.
## Group.
Command|Description
---|---
`group_ext [FILES]`|Group files by extension.
`group_year [FILES]`|Group files and dirs by year.
`group_year_copy <YEAR> [FILES]`|Copy files from current year to the named dir.
## Help.
Command|Description
---|---
`help <FUNCTION>`|Get help about dotfiles bash function.
`h <FUNCTION>`|Short for help.
## Ls.
Command|Description
---|---
`l [DIRS]`|List files in dirs. Current dir by default.
`ll [DIRS]`|List last modified files first. Current dir by default.
`lll [DEPTH] [DIRS]`|List files in tree structure. Current dir by default. Depth can be omitted by passing `-` (dash).
`llll [DIRS]`|List files recursively. Current dir by default.
`la [DIRS]`|List all files in dirs, incl. hidden files. Current dir by default.
`lla [DIRS]`|List all files in dirs, incl. hidden files, sorted by mtime. Current dir by default.
## Markdown.
Command|Description
---|---
`markdown_render <FILE.md>`|Render markdown in browser using Gitea API. Because I want consistency with Gitea web render. Works only inside LAN.
## Name.
Command|Description
---|---
`name [FILES]`|Rename dirs to `snake_case` and files to `PascalCase`. Careful with structured file names like archives!
`name_parse <PARSER> [FILES]`|Rename files with provided parser, i.e. `parse_simple`. All files by default.
`name_hash [FILES]`|Rename all files to their hashes while keeping extensions. All files by default.
`name_hash_check [FILES]`|Check hashes for previously renamed files. All files by default.
`name_show [FILES]`|Rename files for Jellyfin shows, i.e. `Episode S01E01.mkv` All files by default.
`name_manga <SEASON> [FILES]`|Rename files for Kavita manga format. All files by default.
`name_music [FILES]`|Rename files for ffmpeg_music_meta format. All files by default.
`name_ext <EXTENSION> [FILES]`|Rename files with new extension. All files by default.
`name_prefix <OLD> <NEW> [FILES]`|Change file name prefix. All matching files by default.
`name_postfix <OLD> <NEW> [FILES]`|Change file name postfix. All matching files by default.
`name_replace <OLD> <NEW> [FILES]`|Replace part of the name. All matching files by default.
`name_fix_numbering [FILES]`|Fix numbering for numbered files. I.e if there are 10 items and some of them start without zero, then append zero to it. 1..10 -> 01..10.
## Nix.
Command|Description
---|---
`nix_rebuild [HOSTNAME]`|Rebuild system. Optionally force the hostname.
`nix_switch [HOSTNAME]`|Rebuild and switch system. Optionally force the hostname.
`nix_update`|Update system versions.
`nix_shell [NAME]`|Spawn shell with specified nix environment. Uses flake.nix in current dir by default.
`nix_tmpshell <PACKAGES>`|Spawn nix-shell with specified packages.
`nix_live`| Build live image.
## Notify.
Command|Description
---|---
`notify <MESSAGE>`|Send Telegram notification.
`notify_silent <MESSAGE>`|Send silent Telegram notification.
## Own.
Command|Description
---|---
`own [USER] [FILES]`|Change file ownership to specified user id and restrict access to him. Root user by default. This directory recursively by default.
## Pack.
Command|Description
---|---
`pack <TARGET.ext> [FILES]`|Pack files into desired format. All files and directories by default.
`unpack [FILES]`|Attempt to unpack. All supported formats by default.
## Parse.
Command|Description
---|---
`parse_simple <STRING>`|Parse data and output simplified format.
`parse_pascal <STRING>`|Parse to PascalCase.
`parse_snake <STRING>`|Parse to snake_case.
`parse_kebab <STRING>`|Parse to kebab-case.
`parse_camel <STRING>`|Parse to camelCase.
`parse_snake_uppercase <STRING>`|Parse to SNAKE_CASE_UPPERCASE. **NOT STABLE! Repeating results in different output.**
`parse_alnum <STRING>`|Parse data keeping only alphanumeric characters.
`parse_ints <STRING>`|Parse integers from mixed string.
`parse_lowercase <STRING>`|Parse string to lowercase.
`parse_uppercase <STRING>`|Parse string to uppercase.
`parse_titlecase <STRING>`|Parse string to title case.
`parse_sentencecase <STRING>`|Parse string to sentence case.
`parse_startcase <STRING>`|Parse string to start case.
`parse_json <STRING>`|Parse string to pretty Json.
## Permission.
Command|Description
---|---
`perm_share`| Recursively change permissions to allow read sharing with group and others.
`perm`| Recursively change permissions to restrict access for group and others.
## Prune.
Command|Description
---|---
`prune_docker`| Prune everything unused in docker.
`prune_nix`| Prune Nix Store.
`prune_flatpak`| Uninstall flatpaks not listed in the config.
## Ps.
Command|Description
---|---
`fps [PROCESS]`|Find process and filter.
## Random.
Command|Description
---|---
`random_file`| Picks a random file or directory.
## Recursive.
Command|Description
---|---
`recursive <COMMAND>`|Run something recursively over all directories.
`recursive1 <COMMAND>`|Run something recursively over directories of 1 depth (excluding current dir).
## Save.
Command|Description
---|---
`save [TARGETS]`|Backup a game save.
## Ssh.
Command|Description
---|---
`sshmount <REMOTE> <LOCAL>`|Mount FS over ssh. Just extra config for sshfs.
## Su.
Command|Description
---|---
`s [USER]`|Su shortcut for lazy me. Root by default.
## Terminal.
Command|Description
---|---
`tsize`| Get terminal size.
## Tmp.
Command|Description
---|---
`tmp`| CD into host's primary tmp dir.
## Tmux.
Command|Description
---|---
`ta [NAME]`|Create/attach to named session. By default uses current dir name.
`td`| Detach from running session.
`tda`| Detach all other tmux clients.
`tl`| List running sessions.
`tns [NAME]`|Assign name to session. Uses current dir name by default.
`tnw [NAME]`|Assign name to window. Uses current dir name by default.
`tk [NAME]`|Kill specified session. By default uses current dir name.
`tka`| Kill all sessions.
## Todo.
Command|Description
---|---
`todo`| Open `~/.todo.md` file.
## Transcode.
Command|Description
---|---
`transcode <FORMAT> [FILES]`|Convert between different formats. By default tries to convert all files.
## Try.
Command|Description
---|---
`try <COMMAND>`|Retry command every 2 sec until it completes successfully.
## Vdl.
Command|Description
---|---
`vdl [LINK]`|Download video from URL. When no `[LINK]` specified, it tries to update previously downloaded link.
`vdl_vk <LINK>`|Temporary fix for vk downloads.
`vdl_file <FILE>`|Download all videos from file with links.
## Vi.
Command|Description
---|---
`v`| Neovim shortcut.
## Wallpaper.
Command|Description
---|---
`wallpaper <FILE>`|Set specified file as a wallpaper.
## Watch.
Command|Description
---|---
`w <COMMAND>`|Watch command output with 2 seconds interval.
`ww <COMMAND>`|Watch command output with minimal interval.

102
.doc/Navigation.md Normal file
View file

@ -0,0 +1,102 @@
# Navigation.
Navigation principles are shared between Gnome, Tmux and Nvim. The only difference is the *"Leader"* key. Gnome uses *Super* key, Tmux uses *Meta (alt)* key and Nvim uses *Space*. The rest somewhat repeats itself.
## Gnome
Key|Action
---|---
`Super+Esc`|Lauch Terminal emulator.
`Super+q`|Switch to the left workspace.
`Super+e`|Switch to the right workspace.
`Super+Q`|Move window to the left workspace.
`Super+E`|Move window to the right workspace.
`Super+w`|Toggle window maximize.
`Super+s`|Minimize window.
`Super+a`|Snap window to the left.
`Super+d`|Snap window to the right.
`Super+z`|Lock session.
`Super+Z`|Power off.
`Super+x`|Close window.
`Super+c`|Minimize all windows.
`Super+v`|Take a screenshot.
`Super+f`|Toggle window fullscreen.
`Super+\\`|None.
`Super+-`|None.
`Super+=`|None.
`Super+W`|None.
`Super+S`|None.
`Super+A`|None.
`Super+D`|None.
`Super+p`|None.
`Super+n`|None.
`Super+g`|None.
`Super+9`|None.
`Super+0`|None.
## Tmux.
Key|Action
---|---
`Meta+Esc`, `Meta+t`|New window. `Meta+t` is for the Termux Android app as it can't send the `Meta+Esc` combo.
`Meta+q`|Switch to the left window.
`Meta+e`|Switch to the right window.
`Meta+Q`|Move window to the left.
`Meta+E`|Move window to the right.
`Meta+w`|Switch to the above split.
`Meta+s`|Switch to the below split.
`Meta+a`|Switch to the left split.
`Meta+d`|Switch to the right split.
`Meta+z`|Detach from session.
`Meta+Z`|Detach all other clients from session.
`Meta+x`|Close window.
`Meta+x`|Close all other windows.
`Meta+c`|Close split.
`Meta+c`|Close all other splits.
`Meta+v`|Visual selection. `y` to copy.
`Meta+f`|None.
`Meta+\\`|Split vertically.
`Meta+-`|Split horizontally.
`Meta+=`|Equalize splits.
`Meta+W`|Resize split to the up.
`Meta+S`|Resize split to the down.
`Meta+A`|Resize split to the left.
`Meta+D`|Resize split to the right.
`Meta+p`|Scroll up.
`Meta+n`|Scroll down.
`Meta+g`|Switch sessions.
`Meta+9`|Switch to the previous session.
`Meta+0`|Switch to the next session.
## Nvim.
Key|Action
---|---
`Space+Esc`|None.
`Space+q`|Switch to the left buffer.
`Space+e`|Switch to the right buffer.
`Space+Q`|Move buffer to the left.
`Space+E`|Move buffer to the right.
`Space+w`|Switch to the above split.
`Space+s`|Switch to the below split.
`Space+a`|Switch to the left split.
`Space+d`|Switch to the right split.
`Space+z`|Save all and exit.
`Space+x`|Close buffer.
`Space+c`|Close split.
`Space+v`|Visual selection (or just default `v`).
`Space+f`|None.
`Space+\|`|Split vertically.
`Space+-`|Split horizontally.
`Space+=`|Equalize splits.
`Space+W`|Resize split to the up.
`Space+S`|Resize split to the down.
`Space+A`|Resize split to the left.
`Space+D`|Resize split to the right.
`Space+p`|None.
`Space+n`|None.
`Space+g`|None.
`Space+9`|None.
`Space+0`|None.
More info in [Nvim doc.](Nvim.md)

188
.doc/Nvim.md Normal file
View file

@ -0,0 +1,188 @@
# Nvim config.
TODO: preserve default shortcuts, only add new ones when adding new functionality.
TODO: Generate all this similar to the bash `doc_bash`.
## General info.
* Run `:Update` to update everything.
* File tree shows everything by default, telescope ingores git-ignored files.
## Keymaps.
### Common. TODO: separate visual and others from common.
Mode|Key|Action
---|---|---
Normal, Visual|`5dd`|Repeat following command N (5) times.
Normal|`.`|Repeat input on selected line.
Normal, Visual|`<Leader>.`|Repeat command on selected line(s).
Normal|`zz`|Save all files.
Normal|`ZZ`, `<Space>z`|Save all and quit.
Normal|`ZQ`|Quit without saving.
Normal|`v`, `<Space>v`|Visual selection (cursor).
Normal|`V`|Visual selection (lines).
Normal|`<C-v>`|Visual selection (block).
Normal|`gh`|Go to the start of the line.
Normal|`gl`|Go to the end of the line.
Normal|`gj`|Go to the end of the file.
Normal|`gk`|Go to the top of the file.
Normal|`u`|Undo action.
Normal|`U`|Redo action (*remaps*: undo whole line), (*default*: `<C-r>`).
Visual|`u`|Convert selection to lowercase.
Visual|`U`|Convert selection to uppercase.
Visual|`~`|Toggle case.
Normal, Visual|`;`|Enter command mode (*default*: `:`).
Normal|`<Space>0`|Open shortcuts help.
### Align.
Mode|Key|Action
---|---|---
Visual|`<Space>A`|Align selection from the right.
Visual|`<Space>a`|Align selection from the left.
### Autocomplete.
Mode|Key|Action
---|---|---
Input|`<C-Space>`|Autocomplete.
Normal|`<C-Space>`|LSP autocomplete.
### Comments.
Mode|Key|Action
---|---|---
Normal, Visual|`<Space>/`|Toggle selected line(s) comment.
### File tree.
Mode|Key|Action
---|---|---
Normal|`<Space>1`|Toggle file tree.
Normal|`<Tab>`|Toggle directory or open file for preview.
Normal|`a`|Create file/directory.
Normal|`x`|Cut file/directory.
Normal|`p`|Paste file/directory.
Normal|`f`|Filter.
Normal|`F`|Reset filter.
Normal|`d`|Delete file/directory.
Normal|`r`|Rename file.
Normal|`R`|Refresh.
Normal|`s`|Open in system app.
Normal|`S`|Search.
Normal|`I`|Toggle gitignore filter.
Normal|`y`|Copy name.
Normal|`Y`|Copy relative path.
### Fold.
Mode|Key|Action
---|---|---
Normal|`<Space>o`|Toggle fold.
Normal|`<Space>O`|Fold everything.
### Git.
Mode|Key|Action
---|---|---
Normal|`<Space>g`|Toggle git inspection mode.
### Macros.
Mode|Key|Action
---|---|---
Visual|`mwx`|Unwrap selection (select the stuff inside wraps).
Visual|`mw"`|Wrap selection in ".
Visual|`mw3"`|Wrap selection in 3x ".
Visual|`mw'`|Wrap selection in '.
Visual|`mw(`|Wrap selection in ().
Visual|`mw{`|Wrap selection in {}.
Visual|`mw[`|Wrap selection in [].
Visual|`` mw` ``|Wrap selection in \`.
Visual|`` mw3` ``|Wrap selection in 3x \`.
Visual|`mw*`|Wrap selection in *.
Visual|`mw2*`|Wrap selection in 2x *.
Visual|`mw3*`|Wrap selection in 3x *.
Visual|`mw `|Wrap selection in spaces.
Normal, Visual|`mmx`|Markdown: set - [ ] as completed.
Normal, Visual|`mm `|Markdown: set - [x] as not completed.
Normal|`mmp`|Markdown: insert paragrapg (2x non-breakable spaces).
Visual|`mmb`|Markdown: make selection bold.
Visual|`mmi`|Markdown: make selection italic.
Visual|`mms`|Markdown: make selection strikethrough.
Visual|`mmr`|Markdown: make selection a reference.
Visual|`mmc`|Markdown: make selection a code block.
Normal|`mi`|Copy and increment selected line.
Normal|`ma`|Select all.
### Navigation.
Mode|Key|Action
---|---|---
Normal|`<Space>w`|Switch to the split above.
Normal|`<Space>a`|Switch to the split left.
Normal|`<Space>s`|Switch to the split below.
Normal|`<Space>d`|Switch to the split right.
Normal|`<Space>q`|Swtich to the buffer left.
Normal|`<Space>e`|Swtich to the buffer right.
Normal|`<Space>Q`|Move the buffer left.
Normal|`<Space>E`|Move the buffer right.
Normal|`<Space>x`|Close the buffer.
Normal|`<Space>X`|Close all invisible buffers.
Normal|`<Space>m`|Move split.
Normal|`<Space>\|`|Split vertically.
Normal|`<Space>-`|Split horizontally.
Normal|`<Space>c`|Close split.
Input|`<C-h>`|Move left.
Input|`<C-l>`|Move right.
Input|`<C-j>`|Move down.
Input|`<C-k>`|Move up.
### Telescope.
Mode|Key|Action
---|---|---
Normal|`<Space>ff`|Find files.
Normal|`<Space>fg`|Find grep (find text within files).
Normal|`<Space>fb`|Find buffer.
Normal|`<Space>fh`|Find help.
Normal|`<Space>ft`|Find treesitter (vars, functions etc).
Normal|`<Space>fa`|Find all (default treesitter window).
### Terminal.
Mode|Key|Action
---|---|---
Normal|`<Space>4`|Open terminal.
Terminal|`<Esc>`|Detach from terminal.
### To-do.
Write `TODO:` or `NOTE:` to make it searchable.
Mode|Key|Action
---|---|---
Normal|`<Space>3`|Open to-do list.
### Trouble.
Mode|Key|Action
---|---|---
Normal|`<Space>2`|Open LSP trouble list.
### Which key.
Mode|Key|Action
---|---|---
Normal|`<Space>0`|Show context hotkey help.
### Window management.
Mode|Key|Action
---|---|---
Normal|`-`|Decrease split size vertically.
Normal|`_`|Increase split size vertically.
Normal|`\`|Decrease split size horizontally.
Normal|`\|`|Increase split size horizontally.
Normal|`<Space>=`|Equalize split sizes.

9
.editorconfig Normal file
View file

@ -0,0 +1,9 @@
root = true
[*]
end_of_line = lf
charset = utf-8
indent_style = tab
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true

13
Readme.md Normal file
View file

@ -0,0 +1,13 @@
# Custom system config.
This is my own custom config that I use on my GNU/Linux machines. Not meant to be used by anyone else.
For references, go to the [doc directory](src/branch/main/.doc).
# Conventions.
## File namings.
Directory names are `snake_case` so you don't have to release the Shift key 10 times per second when tabing deep for directory.
File names are `PascalCase` to differ from directories, also it works nice with things like my archives where underscore and dash separate extra file data.

555
flake.lock Normal file
View file

@ -0,0 +1,555 @@
{
"nodes": {
"dotfiles": {
"flake": false,
"locked": {
"lastModified": 1709505294,
"narHash": "sha256-DjBl57xU5xGR1ufRzmpO59gYul+AUNczbaMV4r9qrp0=",
"ref": "refs/heads/main",
"rev": "75301239c5857c65a2cf05133171a2f86f5add94",
"revCount": 3,
"type": "git",
"url": "https://git.voronind.com/voronind/nixos.git"
},
"original": {
"type": "git",
"url": "https://git.voronind.com/voronind/nixos.git"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1709485962,
"narHash": "sha256-rmFB4uE10+LJbcVE4ePgiuHOBlUIjQOeZt4VQVJTU8M=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "d579633ff9915a8f4058d5c439281097e92380a8",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "home-manager",
"type": "github"
}
},
"home-manager_2": {
"inputs": {
"nixpkgs": [
"nix-on-droid",
"nixpkgs"
],
"utils": "utils"
},
"locked": {
"lastModified": 1663932797,
"narHash": "sha256-IH8ZBW99W2k7wKLS+Sat9HiKX1TPZjFTnsPizK5crok=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "de3758e31a3a1bc79d569f5deb5dac39791bf9b6",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "home-manager",
"type": "github"
}
},
"nix-formatter-pack": {
"inputs": {
"nixpkgs": [
"nix-on-droid",
"nixpkgs"
],
"nmd": "nmd",
"nmt": "nmt"
},
"locked": {
"lastModified": 1666720474,
"narHash": "sha256-iWojjDS1D19zpeZXbBdjWb9MiKmVVFQCqtJmtTXgPx8=",
"owner": "Gerschtli",
"repo": "nix-formatter-pack",
"rev": "14876cc8fe94a3d329964ecb073b4c988c7b61f5",
"type": "github"
},
"original": {
"owner": "Gerschtli",
"repo": "nix-formatter-pack",
"type": "github"
}
},
"nix-on-droid": {
"inputs": {
"home-manager": "home-manager_2",
"nix-formatter-pack": "nix-formatter-pack",
"nixpkgs": [
"nixpkgs"
],
"nixpkgs-for-bootstrap": "nixpkgs-for-bootstrap",
"nmd": "nmd_2"
},
"locked": {
"lastModified": 1688144254,
"narHash": "sha256-8KL1l/7eP2Zm1aJjdVaSOk0W5kTnJo9kcgW03gqWuiI=",
"owner": "t184256",
"repo": "nix-on-droid",
"rev": "2301e01d48c90b60751005317de7a84a51a87eb6",
"type": "github"
},
"original": {
"owner": "t184256",
"ref": "release-23.05",
"repo": "nix-on-droid",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1707092692,
"narHash": "sha256-ZbHsm+mGk/izkWtT4xwwqz38fdlwu7nUUKXTOmm4SyE=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "faf912b086576fd1a15fca610166c98d47bc667e",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-for-bootstrap": {
"locked": {
"lastModified": 1686921029,
"narHash": "sha256-J1bX9plPCFhTSh6E3TWn9XSxggBh/zDD4xigyaIQBy8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "c7ff1b9b95620ce8728c0d7bd501c458e6da9e04",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "c7ff1b9b95620ce8728c0d7bd501c458e6da9e04",
"type": "github"
}
},
"nmd": {
"flake": false,
"locked": {
"lastModified": 1666190571,
"narHash": "sha256-Z1hc7M9X6L+H83o9vOprijpzhTfOBjd0KmUTnpHAVjA=",
"owner": "rycee",
"repo": "nmd",
"rev": "b75d312b4f33bd3294cd8ae5c2ca8c6da2afc169",
"type": "gitlab"
},
"original": {
"owner": "rycee",
"repo": "nmd",
"type": "gitlab"
}
},
"nmd_2": {
"flake": false,
"locked": {
"lastModified": 1666190571,
"narHash": "sha256-Z1hc7M9X6L+H83o9vOprijpzhTfOBjd0KmUTnpHAVjA=",
"owner": "rycee",
"repo": "nmd",
"rev": "b75d312b4f33bd3294cd8ae5c2ca8c6da2afc169",
"type": "gitlab"
},
"original": {
"owner": "rycee",
"repo": "nmd",
"type": "gitlab"
}
},
"nmt": {
"flake": false,
"locked": {
"lastModified": 1648075362,
"narHash": "sha256-u36WgzoA84dMVsGXzml4wZ5ckGgfnvS0ryzo/3zn/Pc=",
"owner": "rycee",
"repo": "nmt",
"rev": "d83601002c99b78c89ea80e5e6ba21addcfe12ae",
"type": "gitlab"
},
"original": {
"owner": "rycee",
"repo": "nmt",
"type": "gitlab"
}
},
"nvimAlign": {
"flake": false,
"locked": {
"lastModified": 1707650661,
"narHash": "sha256-vq8l6ff3xbdYAdoyZA7VszP7Hl5oVeQCM7n89sxs+Yo=",
"ref": "refs/heads/main",
"rev": "f845218c5fea89e49074e48270dc5e1b9511a0f9",
"revCount": 25,
"type": "git",
"url": "https://git.voronind.com/mirror/mini.align.git"
},
"original": {
"type": "git",
"url": "https://git.voronind.com/mirror/mini.align.git"
}
},
"nvimAutoclose": {
"flake": false,
"locked": {
"lastModified": 1708731776,
"narHash": "sha256-kcPV9NFv0RrilOWwK5qKzcevkD4dC750IKkz1stXhA4=",
"ref": "refs/heads/main",
"rev": "dc42806540dcf448ecb2bad6b67204410cfbe629",
"revCount": 91,
"type": "git",
"url": "https://git.voronind.com/mirror/autoclose.nvim.git"
},
"original": {
"type": "git",
"url": "https://git.voronind.com/mirror/autoclose.nvim.git"
}
},
"nvimBufferline": {
"flake": false,
"locked": {
"lastModified": 1706526490,
"narHash": "sha256-M+QoCYR4WQRqH7KSkdKEBK4MyzPF2uoaA0UtMuc70ic=",
"ref": "refs/heads/main",
"rev": "b15c6daf5a64426c69732b31a951f4e438cb6590",
"revCount": 804,
"type": "git",
"url": "https://git.voronind.com/mirror/bufferline.nvim.git"
},
"original": {
"type": "git",
"url": "https://git.voronind.com/mirror/bufferline.nvim.git"
}
},
"nvimCloseBuffers": {
"flake": false,
"locked": {
"lastModified": 1636931460,
"narHash": "sha256-/jk38ebxKTlyH3AsrSQWMl/cErmu6threyy/MIrdzD4=",
"ref": "refs/heads/master",
"rev": "3acbcad1211572342632a6c0151f839e7dead27f",
"revCount": 45,
"type": "git",
"url": "https://git.voronind.com/mirror/close-buffers.nvim.git"
},
"original": {
"type": "git",
"url": "https://git.voronind.com/mirror/close-buffers.nvim.git"
}
},
"nvimDevicons": {
"flake": false,
"locked": {
"lastModified": 1708217976,
"narHash": "sha256-hMBzqBSHrn4cqV1HBbFJSPR47INNs+jgm54w1f/lAtA=",
"ref": "refs/heads/master",
"rev": "14ac5887110b06b89a96881d534230dac3ed134d",
"revCount": 241,
"type": "git",
"url": "https://git.voronind.com/mirror/nvim-web-devicons.git"
},
"original": {
"type": "git",
"url": "https://git.voronind.com/mirror/nvim-web-devicons.git"
}
},
"nvimGitsigns": {
"flake": false,
"locked": {
"lastModified": 1706372432,
"narHash": "sha256-SLDaqzbvBTTuJEP9H2WOADuxsguMntR+upsGPW8aOEk=",
"ref": "refs/heads/main",
"rev": "2c2463dbd82eddd7dbab881c3a62cfbfbe3c67ae",
"revCount": 818,
"type": "git",
"url": "https://git.voronind.com/mirror/gitsigns.nvim.git"
},
"original": {
"type": "git",
"url": "https://git.voronind.com/mirror/gitsigns.nvim.git"
}
},
"nvimGruvbox": {
"flake": false,
"locked": {
"lastModified": 1707563103,
"narHash": "sha256-1lVNw0WJyS6n306P7ElK15rLnwyv0YD9tCuHs/kTzQM=",
"ref": "refs/heads/master",
"rev": "b17fe51688b76e2ccf118e5f76f3978b9a8c503e",
"revCount": 769,
"type": "git",
"url": "https://git.voronind.com/mirror/gruvbox-material.git"
},
"original": {
"type": "git",
"url": "https://git.voronind.com/mirror/gruvbox-material.git"
}
},
"nvimIndentoMatic": {
"flake": false,
"locked": {
"lastModified": 1685816927,
"narHash": "sha256-scdMOPZZcAxaSf2KN/cOzKFrbv7tm1bwbtV0KgfuUOg=",
"ref": "refs/heads/master",
"rev": "4d11e98f523d3c4500b1dc33f0d1a248a4f69719",
"revCount": 58,
"type": "git",
"url": "https://git.voronind.com/mirror/indent-o-matic.git"
},
"original": {
"type": "git",
"url": "https://git.voronind.com/mirror/indent-o-matic.git"
}
},
"nvimLspconfig": {
"flake": false,
"locked": {
"lastModified": 1708797880,
"narHash": "sha256-FgrTQy9NXjlq+G1W9T9VA7ASJ+qI9891MntlcXVzYqo=",
"ref": "refs/heads/master",
"rev": "b8751ff9ac9fd6ce253e0653d898de02e54040d5",
"revCount": 2762,
"type": "git",
"url": "https://git.voronind.com/mirror/nvim-lspconfig.git"
},
"original": {
"type": "git",
"url": "https://git.voronind.com/mirror/nvim-lspconfig.git"
}
},
"nvimLualine": {
"flake": false,
"locked": {
"lastModified": 1706181415,
"narHash": "sha256-LMMcRY4qnGywdK6Bl4YeAEKLhnRuOZ2txn4oYoso2gI=",
"ref": "refs/heads/master",
"rev": "7d131a8d3ba5016229e8a1d08bf8782acea98852",
"revCount": 678,
"type": "git",
"url": "https://git.voronind.com/mirror/lualine.nvim.git"
},
"original": {
"type": "git",
"url": "https://git.voronind.com/mirror/lualine.nvim.git"
}
},
"nvimOllama": {
"flake": false,
"locked": {
"lastModified": 1703226011,
"narHash": "sha256-LOa56hd92RoGiN6gd4AUUlCLc97URmlFsUvv3HM3XeI=",
"ref": "refs/heads/main",
"rev": "d99e2462be8875602d173c117d5301862669d985",
"revCount": 37,
"type": "git",
"url": "https://git.voronind.com/mirror/ollama.nvim.git"
},
"original": {
"type": "git",
"url": "https://git.voronind.com/mirror/ollama.nvim.git"
}
},
"nvimPlenary": {
"flake": false,
"locked": {
"lastModified": 1706563407,
"narHash": "sha256-AWJHxehKUkEV6N+n78urqHjMVUsMfDK3lvHs/VxhKE8=",
"ref": "refs/heads/master",
"rev": "4f71c0c4a196ceb656c824a70792f3df3ce6bb6d",
"revCount": 354,
"type": "git",
"url": "https://git.voronind.com/mirror/plenary.nvim.git"
},
"original": {
"type": "git",
"url": "https://git.voronind.com/mirror/plenary.nvim.git"
}
},
"nvimSingleComment": {
"flake": false,
"locked": {
"lastModified": 1707312631,
"narHash": "sha256-lMB930CBKbTYBCS08ROPC9gyRYxEHmp/HxCsP9M66/Y=",
"ref": "refs/heads/main",
"rev": "be1cd57abae436f28012f57b2ac8f746cfaa555c",
"revCount": 81,
"type": "git",
"url": "https://git.voronind.com/mirror/SingleComment.nvim.git"
},
"original": {
"type": "git",
"url": "https://git.voronind.com/mirror/SingleComment.nvim.git"
}
},
"nvimTelescope": {
"flake": false,
"locked": {
"lastModified": 1708784664,
"narHash": "sha256-PpUWXgzwUeSZVJg4invL4hk+EAQbxH7+4p8Qo1dUl7g=",
"ref": "refs/heads/master",
"rev": "2e1e382df42467029b493c143c2e727028140214",
"revCount": 1345,
"type": "git",
"url": "https://git.voronind.com/mirror/telescope.nvim.git"
},
"original": {
"type": "git",
"url": "https://git.voronind.com/mirror/telescope.nvim.git"
}
},
"nvimTodo": {
"flake": false,
"locked": {
"lastModified": 1705847650,
"narHash": "sha256-DiyieXXx7iYGWkpeOvduJf0n7dnpaQ7rXmaWvZQaCyE=",
"ref": "refs/heads/main",
"rev": "833d8dd8b07eeda37a09e99460f72a02616935cb",
"revCount": 153,
"type": "git",
"url": "https://git.voronind.com/mirror/todo-comments.nvim.git"
},
"original": {
"type": "git",
"url": "https://git.voronind.com/mirror/todo-comments.nvim.git"
}
},
"nvimTokyonight": {
"flake": false,
"locked": {
"lastModified": 1706697570,
"narHash": "sha256-mzCdcf7FINhhVLUIPv/eLohm4qMG9ndRJ5H4sFU2vO0=",
"ref": "refs/heads/main",
"rev": "610179f7f12db3d08540b6cc61434db2eaecbcff",
"revCount": 571,
"type": "git",
"url": "https://git.voronind.com/mirror/tokyonight.nvim.git"
},
"original": {
"type": "git",
"url": "https://git.voronind.com/mirror/tokyonight.nvim.git"
}
},
"nvimTree": {
"flake": false,
"locked": {
"lastModified": 1708757605,
"narHash": "sha256-8aupc1ZQys6AxWa2XoB0Zobx+liEmxuqlumbgeO2zzY=",
"ref": "refs/heads/master",
"rev": "d52fdeb0a300ac42b9cfa65ae0600a299f8e8677",
"revCount": 1443,
"type": "git",
"url": "https://git.voronind.com/mirror/nvim-tree.lua.git"
},
"original": {
"type": "git",
"url": "https://git.voronind.com/mirror/nvim-tree.lua.git"
}
},
"nvimTreesitter": {
"flake": false,
"locked": {
"lastModified": 1708795279,
"narHash": "sha256-MNIpcwHSq0ltv8UreF9YEvErp/cQHt9tKXJWNSHs+2E=",
"ref": "refs/heads/master",
"rev": "9896ef5f701cc8258c4f04c6944b77e7cfa244e3",
"revCount": 4898,
"type": "git",
"url": "https://git.voronind.com/mirror/nvim-treesitter.git"
},
"original": {
"type": "git",
"url": "https://git.voronind.com/mirror/nvim-treesitter.git"
}
},
"nvimTrouble": {
"flake": false,
"locked": {
"lastModified": 1697626811,
"narHash": "sha256-8nLghiueYOtWY7OGVxow9A2G/5lgt+Kt5D8q1xeJvVg=",
"ref": "refs/heads/main",
"rev": "f1168feada93c0154ede4d1fe9183bf69bac54ea",
"revCount": 250,
"type": "git",
"url": "https://git.voronind.com/mirror/trouble.nvim.git"
},
"original": {
"type": "git",
"url": "https://git.voronind.com/mirror/trouble.nvim.git"
}
},
"nvimWhichKey": {
"flake": false,
"locked": {
"lastModified": 1697801635,
"narHash": "sha256-uvghPj/teWrRMm09Gh8iQ/LV2nYJw0lmoiZK6L4+1cY=",
"ref": "refs/heads/main",
"rev": "4433e5ec9a507e5097571ed55c02ea9658fb268a",
"revCount": 335,
"type": "git",
"url": "https://git.voronind.com/mirror/which-key.nvim.git"
},
"original": {
"type": "git",
"url": "https://git.voronind.com/mirror/which-key.nvim.git"
}
},
"root": {
"inputs": {
"dotfiles": "dotfiles",
"home-manager": "home-manager",
"nix-on-droid": "nix-on-droid",
"nixpkgs": "nixpkgs",
"nvimAlign": "nvimAlign",
"nvimAutoclose": "nvimAutoclose",
"nvimBufferline": "nvimBufferline",
"nvimCloseBuffers": "nvimCloseBuffers",
"nvimDevicons": "nvimDevicons",
"nvimGitsigns": "nvimGitsigns",
"nvimGruvbox": "nvimGruvbox",
"nvimIndentoMatic": "nvimIndentoMatic",
"nvimLspconfig": "nvimLspconfig",
"nvimLualine": "nvimLualine",
"nvimOllama": "nvimOllama",
"nvimPlenary": "nvimPlenary",
"nvimSingleComment": "nvimSingleComment",
"nvimTelescope": "nvimTelescope",
"nvimTodo": "nvimTodo",
"nvimTokyonight": "nvimTokyonight",
"nvimTree": "nvimTree",
"nvimTreesitter": "nvimTreesitter",
"nvimTrouble": "nvimTrouble",
"nvimWhichKey": "nvimWhichKey"
}
},
"utils": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

263
flake.nix Normal file
View file

@ -0,0 +1,263 @@
{
inputs = {
# System.
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
dotfiles = {
url = "git+https://git.voronind.com/voronind/nixos.git";
flake = false;
};
# Android.
nix-on-droid = {
url = "github:t184256/nix-on-droid/release-23.05";
inputs.nixpkgs.follows = "nixpkgs";
};
# Nvim plugins.
nvimAlign = {
url = "git+https://git.voronind.com/mirror/mini.align.git";
flake = false;
};
nvimAutoclose = {
url = "git+https://git.voronind.com/mirror/autoclose.nvim.git";
flake = false;
};
nvimBufferline = {
url = "git+https://git.voronind.com/mirror/bufferline.nvim.git";
flake = false;
};
nvimCloseBuffers = {
url = "git+https://git.voronind.com/mirror/close-buffers.nvim.git";
flake = false;
};
nvimDevicons = {
url = "git+https://git.voronind.com/mirror/nvim-web-devicons.git";
flake = false;
};
nvimGitsigns = {
url = "git+https://git.voronind.com/mirror/gitsigns.nvim.git";
flake = false;
};
nvimGruvbox = {
url = "git+https://git.voronind.com/mirror/gruvbox-material.git";
flake = false;
};
nvimIndentoMatic = {
url = "git+https://git.voronind.com/mirror/indent-o-matic.git";
flake = false;
};
nvimLspconfig = {
url = "git+https://git.voronind.com/mirror/nvim-lspconfig.git";
flake = false;
};
nvimLualine = {
url = "git+https://git.voronind.com/mirror/lualine.nvim.git";
flake = false;
};
nvimOllama = {
url = "git+https://git.voronind.com/mirror/ollama.nvim.git";
flake = false;
};
nvimPlenary = {
url = "git+https://git.voronind.com/mirror/plenary.nvim.git";
flake = false;
};
nvimSingleComment = {
url = "git+https://git.voronind.com/mirror/SingleComment.nvim.git";
flake = false;
};
nvimTelescope = {
url = "git+https://git.voronind.com/mirror/telescope.nvim.git";
flake = false;
};
nvimTodo = {
url = "git+https://git.voronind.com/mirror/todo-comments.nvim.git";
flake = false;
};
nvimTokyonight = {
url = "git+https://git.voronind.com/mirror/tokyonight.nvim.git";
flake = false;
};
nvimTree = {
url = "git+https://git.voronind.com/mirror/nvim-tree.lua.git";
flake = false;
};
nvimTreesitter = {
url = "git+https://git.voronind.com/mirror/nvim-treesitter.git";
flake = false;
};
nvimTrouble = {
url = "git+https://git.voronind.com/mirror/trouble.nvim.git";
flake = false;
};
nvimWhichKey = {
url = "git+https://git.voronind.com/mirror/which-key.nvim.git";
flake = false;
};
};
outputs = { self, nixpkgs, dotfiles, nix-on-droid, home-manager, ... } @inputs: {
# Constant values.
nixosModules.const = {
hashedPassword = "$y$j9T$oqCB16i5E2t1t/HAWaFd5.$tTaHtAcifXaDVpTcRv.yH2/eWKxKE9xM8KcqXHfHrD7"; # Use `mkpasswd`.
stateVersion = "23.11";
};
# Common modules used across all hosts.
nixosModules.common.imports = [
./module/common/AutoUpdate.nix
./module/common/Bash.nix
./module/common/Bootloader.nix
./module/common/Distrobox.nix
./module/common/Dotfiles.nix
./module/common/Environment.nix
./module/common/Filesystem.nix
./module/common/Firefox.nix
./module/common/Firewall.nix
./module/common/Font.nix
./module/common/Git.nix
./module/common/Gtk.nix
./module/common/Kernel.nix
./module/common/Ld.nix
./module/common/Locale.nix
./module/common/Network.nix
./module/common/Nix.nix
./module/common/Nvim.nix
./module/common/Package.nix
./module/common/Root.nix
./module/common/Ssh.nix
./module/common/Sshd.nix
./module/common/Swap.nix
./module/common/Tmux.nix
./module/common/Users.nix
./module/common/Wallpaper.nix
];
# Function to create a host.
mkHost = { system, hostname, modules }: nixpkgs.lib.nixosSystem {
inherit system;
modules = [
./host/${hostname}/Configuration.nix
{ networking.hostName = hostname; }
{ system.stateVersion = inputs.self.nixosModules.const.stateVersion; }
inputs.self.nixosModules.common
home-manager.nixosModules.home-manager
] ++ modules;
specialArgs.const = self.nixosModules.const;
specialArgs.flake = self;
specialArgs.inputs = inputs;
};
# List of all hosts bellow.
nixosConfigurations.dasha = self.mkHost {
hostname = "dasha";
system = "x86_64-linux";
modules = [
./module/AmdGpu.nix
./module/Desktop.nix
./module/Gnome.nix
./module/IntelCpu.nix
./module/PowersaveIntel.nix
./module/Print.nix
./user/Dasha.nix
];
};
nixosConfigurations.desktop = self.mkHost {
hostname = "desktop";
system = "x86_64-linux";
modules = [
./module/AmdCpu.nix
./module/AmdGpu.nix
./module/Desktop.nix
./module/Gnome.nix
./module/Ollama.nix
./module/PowersaveAmd.nix
./module/Print.nix
./module/VirtManager.nix
./user/Voronind.nix
];
};
nixosConfigurations.fsight = self.mkHost {
hostname = "fsight";
system = "x86_64-linux";
modules = [
./module/Docker.nix
];
};
nixosConfigurations.home = self.mkHost {
hostname = "home";
system = "x86_64-linux";
modules = [
./module/AmdCpu.nix
./module/AmdGpu.nix
./module/Docker.nix
./module/Ftpd.nix
./module/Gnome.nix
./module/Ollama.nix
./module/PowersaveAmd.nix
./user/Voronind.nix
];
};
nixosConfigurations.laptop = self.mkHost {
hostname = "laptop";
system = "x86_64-linux";
modules = [
./module/AmdCpu.nix
./module/AmdGpu.nix
./module/Desktop.nix
./module/Gnome.nix
./module/Ollama.nix
./module/PowersaveAmd.nix
./module/Print.nix
./user/Dasha.nix
./user/Voronind.nix
];
};
nixosConfigurations.live = self.mkHost {
hostname = "live";
system = "x86_64-linux";
modules = [
"${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix"
"${nixpkgs}/nixos/modules/installer/cd-dvd/channel.nix"
{ networking.wireless.enable = nixpkgs.lib.mkForce false; }
{ systemd.timers.autoupdate.wantedBy = nixpkgs.lib.mkForce [ ]; }
({ pkgs, ... }: { boot.kernelPackages = nixpkgs.lib.mkForce pkgs.linuxPackages; })
./module/Gnome.nix
];
};
nixosConfigurations.work = self.mkHost {
hostname = "work";
system = "x86_64-linux";
modules = [
./module/Desktop.nix
./module/Gnome.nix
./module/IntelCpu.nix
./module/Ollama.nix
./module/Powerlimit.nix
./module/PowersaveIntel.nix
./module/Print.nix
./user/Voronind.nix
];
};
# Android.
nixOnDroidConfigurations.default = nix-on-droid.lib.nixOnDroidConfiguration {
modules = [
{ system.stateVersion = inputs.self.nixosModules.const.stateVersion; }
./module/NixOnDroid.nix
];
};
};
}

View file

@ -0,0 +1,21 @@
{ lib, ... }: {
imports = [
./Tablet.nix
];
# Disable flatpak install.
systemd.services.flatpakinstall.wantedBy = lib.mkForce [ ];
# Filesystems.
fileSystems."/storage/hot" = {
device = "/dev/storage/hot";
fsType = "ext4";
options = [ "nofail" ];
};
fileSystems."/storage/cold" = {
device = "/dev/storage/cold";
fsType = "ext4";
options = [ "nofail" ];
};
}

6
host/dasha/Tablet.nix Normal file
View file

@ -0,0 +1,6 @@
{ pkgs, ... }: {
hardware.opentabletdriver.enable = true;
environment.systemPackages = with pkgs; [
krita
];
}

View file

@ -0,0 +1,22 @@
{ config, pkgs, ... }: {
imports = [ ];
# Filesystems.
fileSystems."/storage/hot" = {
device = "/dev/storage/hot";
fsType = "ext4";
options = [ "nofail" ];
};
fileSystems."/storage/cold_1" = {
device = "/dev/storage/cold_1";
fsType = "ext4";
options = [ "noauto" "nofail" ];
};
fileSystems."/storage/cold_2" = {
device = "/dev/storage/cold_2";
fsType = "ext4";
options = [ "noauto" "nofail" ];
};
}

View file

@ -0,0 +1,22 @@
{ lib, ... }: {
imports = [ ];
# Grub.
boot.loader.systemd-boot.enable = lib.mkForce false;
boot.loader.efi.canTouchEfiVariables = lib.mkForce false;
boot.loader.grub.enable = true;
boot.loader.grub.device = "/dev/sda";
boot.loader.grub.useOSProber = true;
fileSystems."/" = lib.mkForce {
device = "/dev/sda2";
fsType = "ext4";
};
fileSystems."/boot" = lib.mkForce {
device = "/dev/sda1";
fsType = "vfat";
};
# Root password.
users.users.root.hashedPassword = lib.mkForce "$y$j9T$d4HfwutZr.eNHuLJYRuro/$7swZfgCNS6jEXHFCxsW5um/68jX9BRiiZD1BYcm/gD/";
}

28
host/home/Backup.nix Normal file
View file

@ -0,0 +1,28 @@
{ pkgs, ... }: {
systemd.services.backup = {
enable = true;
description = "Home system backup.";
serviceConfig = {
Type = "oneshot";
ExecStart = "/root/app/bin/home/Backup";
};
path = with pkgs; [
bashInteractive
curl
gnutar
gzip
gawk
pv
];
# wantedBy = [ "multi-user.target" ];
};
systemd.timers.backup = {
timerConfig = {
OnCalendar = "*-*-* 06:00:00";
Persistent = true;
Unit = "backup.service";
};
wantedBy = [ "timers.target" ];
};
}

View file

@ -0,0 +1,46 @@
{ config, pkgs, lib, ... }: {
imports = [
./Backup.nix
./GnomeRdp.nix
./Nextcloud.nix
./PhotosProcess.nix
./YandexMusic.nix
];
# Network.
networking.networkmanager.insertNameservers = [
"1.1.1.1"
"8.8.8.8"
];
networking.extraHosts = ''
10.1.0.2 git.voronind.com
10.1.0.2 iot.voronind.com
10.1.0.2 pass.voronind.com
'';
# Filesystems.
fileSystems."/storage/cold_1" = {
device = "/dev/storage/cold_1";
fsType = "ext4";
options = [ "noauto" "nofail" ];
};
fileSystems."/storage/cold_2" = {
device = "/dev/storage/cold_2";
fsType = "ext4";
options = [ "noauto" "nofail" ];
};
fileSystems."/storage/hot" = {
device = "/dev/storage/hot";
fsType = "ext4";
options = [ "noauto" "nofail" ];
};
# Disable Docker autostart.
systemd.services.docker.wantedBy = lib.mkForce [ ];
systemd.sockets.docker.wantedBy = lib.mkForce [ ];
# Disable ftpd autostart.
systemd.services.vsftpd.wantedBy = lib.mkForce [ ];
}

6
host/home/GnomeRdp.nix Normal file
View file

@ -0,0 +1,6 @@
{ pkgs, ... }: {
environment.systemPackages = with pkgs; [
openssl
gnome.gnome-remote-desktop
];
}

24
host/home/Nextcloud.nix Normal file
View file

@ -0,0 +1,24 @@
{ pkgs, ... }: {
systemd.services.nextcloud = {
enable = true;
description = "Nextcloud worker.";
serviceConfig = {
Type = "oneshot";
ExecStart = "/root/app/bin/home/Nextcloud";
};
path = with pkgs; [
bashInteractive
docker
];
# wantedBy = [ "multi-user.target" ];
};
systemd.timers.nextcloud = {
timerConfig = {
OnCalendar = "hourly";
Persistent = false;
Unit = "nextcloud.service";
};
wantedBy = [ "timers.target" ];
};
}

View file

@ -0,0 +1,24 @@
{ pkgs, ... }: {
systemd.services.photos_process = {
enable = true;
description = "Process uploaded photos.";
serviceConfig = {
Type = "oneshot";
ExecStart = "/root/app/bin/home/PhotosProcess";
};
path = with pkgs; [
bashInteractive
docker
];
# wantedBy = [ "multi-user.target" ];
};
systemd.timers.photos_process = {
timerConfig = {
OnCalendar = "daily";
Persistent = true;
Unit = "photos_process.service";
};
wantedBy = [ "timers.target" ];
};
}

24
host/home/YandexMusic.nix Normal file
View file

@ -0,0 +1,24 @@
{ pkgs, ... }: {
systemd.services.yandex_music = {
enable = true;
description = "Sync music from Yandex.Music.";
serviceConfig = {
Type = "oneshot";
ExecStart = "/root/app/bin/home/YandexMusic";
};
path = with pkgs; [
bashInteractive
docker
];
# wantedBy = [ "multi-user.target" ];
};
systemd.timers.yandex_music = {
timerConfig = {
OnCalendar = "daily";
Persistent = true;
Unit = "yandex_music.service";
};
wantedBy = [ "timers.target" ];
};
}

View file

@ -0,0 +1,15 @@
{ config, pkgs, environment, ... }: {
imports = [ ];
# Use dedicated GPU by default.
environment.variables = {
DRI_PRIME = "1";
};
# Filesystems.
fileSystems."/storage/hot" = {
device = "/dev/storage/hot";
fsType = "ext4";
options = [ "nofail" ];
};
}

View file

@ -0,0 +1,5 @@
{ config, pkgs, ... }: {
imports = [ ];
environment.systemPackages = with pkgs; [ ];
}

View file

@ -0,0 +1,5 @@
{ config, pkgs, ... }: {
imports = [
./Fprint.nix
];
}

9
host/work/Fprint.nix Normal file
View file

@ -0,0 +1,9 @@
{ pkgs, ... }: {
environment.systemPackages = with pkgs; [
fprintd
];
services.fprintd.enable = true;
services.fprintd.tod.enable = true;
services.fprintd.tod.driver = pkgs.libfprint-2-tod1-vfs0090;
}

4
module/AmdCpu.nix Normal file
View file

@ -0,0 +1,4 @@
{ lib, config, ... }: {
boot.kernelModules = [ "kvm-amd" ];
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

14
module/AmdGpu.nix Normal file
View file

@ -0,0 +1,14 @@
{ pkgs, environment, ... }: {
boot.initrd.kernelModules = [ "amdgpu" ];
services.xserver.videoDrivers = [ "amdgpu" ];
hardware.opengl.driSupport = true;
hardware.opengl.driSupport32Bit = true;
environment.variables.AMD_VULKAN_ICD = "RADV";
# AMDVLK was broken for me (huge stuttering). So keep it disabled, at least for now.
# hardware.opengl.extraPackages = with pkgs; [
# amdvlk
# ];
# hardware.opengl.extraPackages32 = with pkgs; [
# driversi686Linux.amdvlk
# ];
}

29
module/Desktop.nix Normal file
View file

@ -0,0 +1,29 @@
{ pkgs, ... }: {
environment.systemPackages = with pkgs; [
android-studio
blender-hip
bottles
gimp
gradience
jellyfin
jetbrains.idea-community
obs-studio
onlyoffice-bin
tor-browser
];
hardware.opengl = let
packages = with pkgs; [
dxvk
gamescope
mangohud
vkd3d
];
in {
extraPackages = packages;
extraPackages32 = packages;
};
# Special packages.
programs.steam.enable = true;
}

5
module/Docker.nix Normal file
View file

@ -0,0 +1,5 @@
{ environment, ... }: {
environment.etc.docker.source = ./docker;
environment.variables.DOCKER_CONFIG = "/etc/docker";
virtualisation.docker.enable = true;
}

View file

@ -0,0 +1,9 @@
{ ... }: {
environment.etc.docker.source = ./docker;
environment.variables.DOCKER_CONFIG = "/etc/docker";
virtualisation.docker.enable = true;
virtualisation.docker.rootless = {
enable = true;
setSocketVariable = true;
};
}

19
module/Flatpak.nix Normal file
View file

@ -0,0 +1,19 @@
{ pkgs, lib, ... }: let
list = "~/.config/linux/Flatpak.txt";
in {
# Enable Flatpaks.
services.flatpak.enable = true;
# Bootstrap apps on boot.
systemd.services.flatpakinstall = {
description = "Install Flatpak apps.";
wantedBy = [ "multi-user.target" ];
wants = [ "dotfiles.service" ];
after = [ "dotfiles.service" ];
serviceConfig.Type = "oneshot";
script = ''
${lib.getExe pkgs.flatpak} remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
[[ -f ${list} ]] && cat ${list} | cut -f2 | ${lib.getExe pkgs.parallel} -j1 -- ${lib.getExe pkgs.flatpak} install -y --system {}
'';
};
}

17
module/Ftpd.nix Normal file
View file

@ -0,0 +1,17 @@
{ ... }: {
services.vsftpd = {
enable = true;
anonymousUser = true;
anonymousUserNoPassword = true;
anonymousUploadEnable = true;
anonymousMkdirEnable = true;
anonymousUmask = "000";
anonymousUserHome = "/storage/hot/ftp";
allowWriteableChroot = true;
writeEnable = true;
localUsers = false;
extraConfig = ''
anon_other_write_enable=YES
'';
};
}

391
module/Gnome.nix Normal file
View file

@ -0,0 +1,391 @@
{ pkgs, lib, ... }: let
dconfConfig = "~/.config/linux/Gnome.dconf";
in {
# GUI.
services.xserver.enable = true;
services.xserver.displayManager.gdm.enable = true;
services.xserver.desktopManager.gnome.enable = true;
services.xserver.xkb = {
layout = "us,ru";
options = "grp:caps_toggle,lv3:ralt_switch";
};
# Specify default apps.
xdg.mime.defaultApplications = {
"image/png" = "org.gnome.Loupe.desktop";
"image/jpeg" = "org.gnome.Loupe.desktop";
"image/jxl" = "org.gnome.Loupe.desktop";
};
# Disable some apps.
services.gnome.gnome-keyring.enable = lib.mkForce false;
environment.gnome.excludePackages = with pkgs.gnome; [
# baobab # Disk usage analyzer.
# cheese # Photo booth.
# epiphany # Web browser.
# simple-scan # Document scanner.
# totem # Video player.
# yelp # Help viewer.
# file-roller # Archive manager.
# geary # Email client.
# seahorse # Password manager.
# gnome-calculator
# gnome-calendar
# gnome-characters
# gnome-clocks
# gnome-contacts
# gnome-font-viewer
# gnome-keyring
# gnome-logs
# gnome-maps
# gnome-music
# gnome-shell-extensions
gnome-software
# gnome-system-monitor
# gnome-weather
# gnome-disk-utility
# pkgs.gnome-text-editor
];
# Sound.
sound.enable = true;
hardware.pulseaudio.enable = false;
security.rtkit.enable = true;
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
};
# Enable dconf.
programs.dconf.enable = true;
programs.dconf.profiles.user = {
enableUserDb = true; # Delete `~/.config/dconf/user` to reset user settings.
databases = [{
settings = with lib.gvariant; {
"org/gnome/desktop/a11y" = {
always-show-universal-access-status = true;
};
"org/gnome/desktop/background" = {
color-shading-type = "solid";
picture-options = "zoom";
picture-uri = "file:///etc/wallpaper/Forest.jpg";
picture-uri-dark = "file:///etc/wallpaper/Forest.jpg";
primary-color = "#000000000000";
secondary-color = "#000000000000";
};
"org/gnome/desktop/input-sources" = {
current = mkUint32 0;
mru-sources = [ (mkTuple [ "xkb" "us" ]) (mkTuple [ "xkb" "ru" ]) ];
per-window = false;
show-all-sources = true;
sources = [ (mkTuple [ "xkb" "us" ]) (mkTuple [ "xkb" "ru" ]) ];
xkb-options = [ "grp:caps_toggle" "lv3:ralt_switch" ];
};
"org/gnome/desktop/interface" = {
clock-show-date = true;
clock-show-weekday = true;
color-scheme = "prefer-dark";
cursor-blink = false;
cursor-size = "24";
cursor-theme = "Adwaita";
document-font-name = "SF Pro Text 11";
enable-animations = false;
enable-hot-corners = false;
font-antialiasing = "rgba";
font-hinting = "full";
font-name = "SF Pro Display 10";
gtk-enable-primary-paste = false;
gtk-theme = "Adwaita";
icon-theme = "Adwaita";
monospace-font-name = "Terminess Nerd Font Mono Medium 12";
show-battery-percentage = false;
toolbar-style = "text";
toolkit-accessibility = false;
};
"org/gnome/desktop/media-handling" = {
automount = false;
automount-open = false;
autorun-never = true;
};
"org/gnome/desktop/peripherals/mouse" = {
accel-profile = "flat";
natural-scroll = true;
speed = "0.0";
};
"org/gnome/desktop/peripherals/touchpad" = {
tap-to-click = true;
two-finger-scrolling-enabled = true;
};
"org/gnome/desktop/privacy" = {
disable-camera = false;
disable-microphone = false;
old-files-age = mkUint32 30;
recent-files-max-age = mkUint32 30;
remove-old-temp-files = true;
remove-old-trash-files = true;
report-technical-problems = true;
};
"org/gnome/desktop/remote-desktop/rdp" = {
enable = false;
tls-cert = "/home/voronind/.local/share/gnome-remote-desktop/tls.crt";
tls-key = "/home/voronind/.local/share/gnome-remote-desktop/tls.key";
view-only = true;
};
"org/gnome/desktop/screensaver" = {
color-shading-type = "solid";
idle-activation-enabled = false;
lock-delay = mkUint32 0;
picture-options = "zoom";
picture-uri = "file:///etc/wallpaper/Forest.jpg";
primary-color = "#000000000000";
secondary-color = "#000000000000";
};
"org/gnome/desktop/sound" = {
allow-volume-above-100-percent = false;
event-sounds = false;
theme-name = "freedesktop";
};
"org/gnome/desktop/wm/keybindings" = {
activate-window-menu = [ "" ];
begin-move = [ "" ];
begin-resize = [ "<Super>r" ];
close = [ "<Super>x" ];
cycle-group = [ "" ];
cycle-group-backward = [ "" ];
cycle-panels = [ "" ];
cycle-panels-backward = [ "" ];
cycle-windows = [ "" ];
cycle-windows-backward = [ "" ];
maximize = [ "" ];
maximize-horizontally = [ "" ];
minimize = [ "<Super>s" ];
move-to-monitor-down = [ "" ];
move-to-monitor-left = [ "" ];
move-to-monitor-right = [ "" ];
move-to-monitor-up = [ "" ];
move-to-workspace-1 = [ "" ];
move-to-workspace-2 = [ "" ];
move-to-workspace-3 = [ "" ];
move-to-workspace-4 = [ "" ];
move-to-workspace-last = [ "" ];
move-to-workspace-left = [ "<Shift><Super>q" ];
move-to-workspace-right = [ "<Shift><Super>e" ];
panel-run-dialog = [ "<Super>space" ];
show-desktop = [ "<Super>c" ];
switch-applications = [ "<Super>Tab" ];
switch-applications-backward = [ "<Shift><Super>Tab" ];
switch-group = [ "<Alt>Tab" ];
switch-group-backward = [ "<Shift><Alt>Tab" ];
switch-input-source = [ "" ];
switch-input-source-backward = [ "" ];
switch-panels = [ "" ];
switch-panels-backward = [ "" ];
switch-to-workspace-1 = [ "" ];
switch-to-workspace-2 = [ "" ];
switch-to-workspace-3 = [ "" ];
switch-to-workspace-4 = [ "" ];
switch-to-workspace-last = [ "" ];
switch-to-workspace-left = [ "<Super>q" ];
switch-to-workspace-right = [ "<Super>e" ];
switch-windows = [ "" ];
switch-windows-backward = [ "" ];
toggle-fullscreen = [ "<Super>f" ];
toggle-maximized = [ "<Super>w" ];
unmaximize = [ "" ];
};
"org/gnome/desktop/wm/preferences" = {
action-middle-click-titlebar = "minimize";
action-right-click-titlebar = "menu";
focus-mode = "click";
button-layout = "appmenu:close";
titlebar-font = "SF Pro Display 11";
};
"org/gnome/desktop/session" = {
idle-delay = mkUint32 0;
};
"org/gnome/mutter" = {
attach-modal-dialogs = true;
center-new-windows = true;
dynamic-workspaces = true;
edge-tiling = true;
workspaces-only-on-primary = true;
};
"org/gnome/mutter/keybindings" = {
toggle-tiled-left = [ "<Super>a" ];
toggle-tiled-right = [ "<Super>d" ];
};
"org/gnome/mutter/wayland/keybindings" = {
restore-shortcuts = [ "" ];
};
"org/gnome/nautilus/icon-view" = {
default-zoom-level = "larger";
};
"org/gnome/nautilus/list-view" = {
default-zoom-level = "small";
use-tree-view = false;
};
"org/gnome/nautilus/preferences" = {
click-policy = "single";
default-folder-viewer = "list-view";
default-sort-in-reverse-order = false;
default-sort-order = "name";
migrated-gtk-settings = true;
search-filter-time-type = "last_modified";
search-view = "list-view";
show-image-thumbnails = "local-only";
};
"org/gnome/settings-daemon/plugins/color" = {
night-light-enabled = false;
night-light-schedule-automatic = false;
night-light-schedule-from = "0.0";
night-light-schedule-to = "0.0";
night-light-temperature = mkUint32 3700;
};
"org/gnome/settings-daemon/plugins/media-keys" = {
custom-keybindings = [
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/"
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1/"
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom2/"
];
magnifier = [ "" ];
magnifier-zoom-in = [ "" ];
magnifier-zoom-out = [ "" ];
screenreader = [ "" ];
screensaver = [ "<Super>z" ];
};
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0" = {
binding = "<Super>Escape";
command = "kgx";
name = "gnome-terminal";
};
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1" = {
binding = "<Shift><Super>z";
command = "gnome-session-quit --power-off";
name = "gnome-poweroff";
};
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom2" = {
binding = "<Primary>Escape";
command = "kgx -- btop";
name = "System Monitor";
};
"org/gnome/settings-daemon/plugins/power" = {
ambient-enabled = false;
idle-dim = false;
power-button-action = "nothing";
sleep-inactive-ac-timeout = "900";
sleep-inactive-ac-type = "nothing";
sleep-inactive-battery-type = "nothing";
};
"org/gnome/shell" = {
disable-extension-version-validation = true;
disable-user-extensions = false;
favorite-apps = [ "" ];
had-bluetooth-devices-setup = true;
last-selected-power-profile = "power-saver";
remember-mount-password = false;
};
"org/gnome/shell/app-switcher" = {
current-workspace-only = true;
};
"org/gnome/shell/keybindings" = {
focus-active-notification = [ "" ];
open-application-menu = [ "" ];
show-screenshot-ui = [ "<Super>v" ];
switch-to-application-1 = [ "" ];
switch-to-application-2 = [ "" ];
switch-to-application-3 = [ "" ];
switch-to-application-4 = [ "" ];
switch-to-application-5 = [ "" ];
switch-to-application-6 = [ "" ];
switch-to-application-7 = [ "" ];
switch-to-application-8 = [ "" ];
switch-to-application-9 = [ "" ];
toggle-application-view = [ "" ];
toggle-message-tray = [ "" ];
toggle-overview = [ "" ];
toggle-quick-settings = [ "" ];
};
"org/gnome/shell/overrides" = {
edge-tiling = false;
};
"org/gnome/software" = {
download-updates = false;
download-updates-notify = false;
first-run = false;
show-nonfree-prompt = false;
};
"org/gnome/system/location" = {
enabled = false;
};
"org/gtk/gtk4/settings/file-chooser" = {
date-format = "regular";
location-mode = "path-bar";
show-hidden = false;
show-size-column = true;
show-type-column = true;
sidebar-width = "166";
sort-column = "modified";
sort-directories-first = true;
sort-order = "descending";
type-format = "category";
view-type = "list";
};
"org/gtk/settings/file-chooser" = {
date-format = "regular";
location-mode = "path-bar";
show-hidden = false;
show-size-column = true;
show-type-column = true;
sort-column = "modified";
sort-directories-first = true;
sort-order = "descending";
type-format = "category";
};
"system/locale" = {
region = "ru_RU.UTF-8";
};
"system/proxy" = {
mode = "none";
};
};
}];
};
}

3
module/IntelCpu.nix Normal file
View file

@ -0,0 +1,3 @@
{ ... }: {
boot.kernelModules = [ "kvm-intel" ];
}

40
module/NixOnDroid.nix Normal file
View file

@ -0,0 +1,40 @@
{ pkgs, ... }: {
environment.packages = with pkgs; [
android-tools
binwalk
coreutils
curl
diffutils
ffmpeg
file
findutils
gcc
git
gnugrep
gnumake
gnused
gnutar
gzip
hostname
imagemagick
jq
lsof
ltex-ls
man
ncdu
neovim
nmap
openssh
parallel
pv
ripgrep
sqlite
tmux
tree
utillinux
wget
xz
yt-dlp
zip unzip
];
}

24
module/Ollama.nix Normal file
View file

@ -0,0 +1,24 @@
{ pkgs, lib, ... }: {
environment.systemPackages = with pkgs; [ ollama ];
systemd.services.ollama = {
description = "Ollama LLM server.";
wantedBy = [ "multi-user.target" ];
wants = [ "NetworkManager-wait-online.service" ];
after = [ "NetworkManager-wait-online.service" ];
serviceConfig.Type = "simple";
script = ''
HOME=/root ${lib.getExe pkgs.ollama} serve
'';
};
systemd.services.ollamamodel = {
description = "Ollama LLM model.";
wantedBy = [ "multi-user.target" ];
wants = [ "ollama.service" ];
after = [ "ollama.service" ];
serviceConfig.Type = "simple";
script = ''
sleep 5
${lib.getExe pkgs.ollama} pull mistral
'';
};
}

13
module/Powerlimit.nix Normal file
View file

@ -0,0 +1,13 @@
{ pkgs, lib, ... }: {
systemd.services.powerlimit = {
description = "Limit battery charge.";
enable = true;
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "simple";
RemainAfterExit = "yes";
ExecStart = "${lib.getExe pkgs.bash} -c 'echo 40 > /sys/class/power_supply/BAT0/charge_control_start_threshold; echo 80 > /sys/class/power_supply/BAT0/charge_control_end_threshold;'";
ExecStop = "${lib.getExe pkgs.bash} -c 'echo 95 > /sys/class/power_supply/BAT0/charge_control_end_threshold; echo 90 > /sys/class/power_supply/BAT0/charge_control_start_threshold;'";
};
};
}

16
module/PowersaveAmd.nix Normal file
View file

@ -0,0 +1,16 @@
{ pkgs, lib, ... }: {
# Requirements:
# CPPC (Collaborative Power Control) - Disabled.
# PSS (Cool and Quiet) - Enabled.
systemd.services.powersave = {
description = "AMD disable Boost";
enable = true;
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "simple";
RemainAfterExit = "yes";
ExecStart = "${lib.getExe pkgs.bash} -c 'echo 0 > /sys/devices/system/cpu/cpufreq/boost'";
ExecStop = "${lib.getExe pkgs.bash} -c 'echo 1 > /sys/devices/system/cpu/cpufreq/boost'";
};
};
}

13
module/PowersaveIntel.nix Normal file
View file

@ -0,0 +1,13 @@
{ pkgs, lib, ... }: {
systemd.services.powersave = {
description = "Intel disable Boost";
enable = true;
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "simple";
RemainAfterExit = "yes";
ExecStart = "${lib.getExe pkgs.bash} -c 'echo 1 > /sys/devices/system/cpu/intel_pstate/no_turbo'";
ExecStop = "${lib.getExe pkgs.bash} -c 'echo 0 > /sys/devices/system/cpu/intel_pstate/no_turbo'";
};
};
}

9
module/Print.nix Normal file
View file

@ -0,0 +1,9 @@
{ ... }: {
services.printing = {
enable = true;
clientConf = ''
DigestOptions DenyMD5
ServerName 192.168.1.2
'';
};
}

4
module/VirtManager.nix Normal file
View file

@ -0,0 +1,4 @@
{ pkgs, ... }: {
virtualisation.libvirtd.enable = true;
programs.virt-manager.enable = true;
}

View file

@ -0,0 +1,10 @@
{ pkgs, inputs, lib, config, ... }: {
system.autoUpgrade = {
enable = true;
allowReboot = false;
dates = "daily";
flake = "/root/.config/linux/system";
operation = "boot";
persistent = true;
};
}

7
module/common/Bash.nix Normal file
View file

@ -0,0 +1,7 @@
{ environment, lib, ... }: {
environment.etc.bash.source = ./bash;
environment.shellAliases = lib.mkForce {};
environment.variables.BASH_MODULE_PATH = "/etc/bash/module/";
environment.variables.BASH_PATH = "/etc/bash/";
programs.bash.interactiveShellInit = "source /etc/bash/Bashrc.sh";
}

View file

@ -0,0 +1,21 @@
{ lib, ... }: {
# Enable non-free firmware.
hardware.enableRedistributableFirmware = lib.mkDefault true;
# Configure bootloader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
boot.loader.systemd-boot.configurationLimit = 7;
boot.initrd.kernelModules = [ "dm-snapshot" ];
boot.initrd.availableKernelModules = [
"ahci"
"ata_piix"
"mptspi"
"nvme"
"sd_mod"
"sr_mod"
"usb_storage"
"usbhid"
"xhci_pci"
];
}

9
module/common/Direnv.nix Normal file
View file

@ -0,0 +1,9 @@
{ ... }: {
packages.direnv = {
enable = true;
silent = true;
direnvrcExtra = ''
export NIX_SHELL="direnv"
'';
};
}

View file

@ -0,0 +1,13 @@
{ pkgs, ... }: {
environment.systemPackages = with pkgs; [
distrobox
];
virtualisation = {
podman = {
enable = true;
defaultNetwork.settings.dns_enabled = false;
dockerCompat = false;
};
};
}

View file

@ -0,0 +1,3 @@
{ inputs, ... }: {
environment.etc.dotfiles.source = inputs.dotfiles;
}

View file

@ -0,0 +1,18 @@
{ environment, pkgs, ... }: {
security.loginDefs.settings.UMASK = "077";
environment.variables = {
# Neovim.
EDITOR = "nvim";
MANPAGER = "nvim +Man!";
# Mangohud.
MANGOHUD = "1";
MANGOHUD_CONFIG = "no_display=0,hud_no_margin=1,font_size=12,toggle_hud=F1,fps_sampling_period=1000,fps_limit=165,fps_limit_method=early,af=16,vsync=3,gl_vsync=1,throttling_status=1,cpu_temp=1,gpu_temp=1,gpu_junction_temp=1,device_battery=gamepad,mouse,frame_timing=0,benchmark_percentiles=0,battery=1,battery_time=1,time=1,ram=1,vram=1,swap=1";
# Proton.
WINEFSYNC = "1";
# Nix.
NIX_CURRENT_SYSTEM = "${pkgs.stdenv.system}";
};
}

View file

@ -0,0 +1,10 @@
{ ... }: {
fileSystems."/" = {
device = "/dev/disk/by-partlabel/NIXROOT";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-partlabel/NIXBOOT";
fsType = "vfat";
};
}

137
module/common/Firefox.nix Normal file
View file

@ -0,0 +1,137 @@
{ pkgs, environment, ... }: {
# Disable profile switching on rebuild.
environment.variables.MOZ_LEGACY_PROFILES = "1";
programs.firefox = {
enable = true;
package = pkgs.firefox-esr;
languagePacks = [ "en-US" "ru" ];
autoConfig = ''
// Bookmarks.
lockPref("browser.microsummary.enabled", true);
lockPref("browser.places.importBookmarksHTML", true);
lockPref("browser.toolbars.bookmarks.visibility", "never");
// Fonts.
pref("browser.display.use_document_fonts", 0);
lockPref("font.minimum-size.x-cyrillic", 12);
lockPref("font.minimum-size.x-unicode", 12);
lockPref("font.minimum-size.x-western", 12);
lockPref("font.name.monospace.x-cyrillic", "Terminess Nerd Font Mono");
lockPref("font.name.monospace.x-unicode", "Terminess Nerd Font Mono");
lockPref("font.name.monospace.x-western", "Terminess Nerd Font Mono");
lockPref("font.name.sans-serif.x-cyrillic", "SF Pro Text");
lockPref("font.name.sans-serif.x-unicode", "SF Pro Text");
lockPref("font.name.sans-serif.x-western", "SF Pro Text");
lockPref("font.name.serif.x-cyrillic", "SF Pro Text");
lockPref("font.name.serif.x-unicode", "SF Pro Text");
lockPref("font.name.serif.x-western", "SF Pro Text");
// Animations.
lockPref("browser.fullscreen.animateUp", 0);
lockPref("browser.fullscreen.autohide", true);
// Homepage.
lockPref("browser.newtabpage.enabled", false);
lockPref("browser.startup.homepage", "https://home.voronind.com/");
lockPref("browser.startup.page", 3);
// Passwords.
lockPref("signon.prefillForms", false);
lockPref("signon.rememberSignons", false);
// Formats.
lockPref("image.jxl.enabled", true);
'';
policies = {
ManagedBookmarks = [
{
toplevel_name = "Pin";
} {
url = "https://home.voronind.com";
name = "Dashboard";
} {
url = "https://music.yandex.ru";
name = "Music";
} {
url = "https://web.telegram.org";
name = "Telegram";
} {
url = "https://discord.com";
name = "Discord";
} {
url = "https://mail.fsight.ru";
name = "Work Mail";
} {
url = "https://git.voronind.com";
name = "Git";
} {
url = "https://git.fmp.fsight.world";
name = "Work Git";
} {
url = "https://support.fsight.ru";
name = "Work Board";
} {
url = "https://iot.voronind.com";
name = "Hass";
} {
url = "https://cloud.voronind.com";
name = "Cloud";
}
];
ExtensionUpdate = true;
ExtensionSettings = {
"*" = {
install_sources = [ "*" ];
installation_mode = "blocked";
};
# "queryamoid@kaply.com" = {
# installation_mode = "force_installed";
# install_url = "https://github.com/mkaply/queryamoid/releases/download/v0.1/query_amo_addon_id-0.1-fx.xpi";
# };
"{446900e4-71c2-419f-a6a7-df9c091e268b}" = {
installation_mode = "force_installed";
install_url = "https://addons.mozilla.org/firefox/downloads/latest/bitwarden-password-manager/latest.xpi";
};
"cliget@zaidabdulla.com" = {
installation_mode = "force_installed";
install_url = "https://addons.mozilla.org/firefox/downloads/latest/cliget/latest.xpi";
};
"addon@darkreader.org" = {
installation_mode = "force_installed";
install_url = "https://addons.mozilla.org/firefox/downloads/latest/darkreader/latest.xpi";
};
"{e7625f06-e252-479d-ac7a-db68aeaff2cb}" = {
installation_mode = "force_installed";
install_url = "https://addons.mozilla.org/firefox/downloads/latest/togglefonts/latest.xpi";
};
"uBlock0@raymondhill.net" = {
installation_mode = "force_installed";
install_url = "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi";
};
"{d7742d87-e61d-4b78-b8a1-b469842139fa}" = {
installation_mode = "force_installed";
install_url = "https://addons.mozilla.org/firefox/downloads/latest/vimium-ff/latest.xpi";
};
"{08d5243b-4236-4a27-984b-1ded22ce01c3}" = {
installation_mode = "force_installed";
install_url = "https://addons.mozilla.org/firefox/downloads/latest/gruvboxgruvboxgruvboxgruvboxgr/latest.xpi";
};
};
SearchEngines = {
Default = "Whoogle";
Add = [
{
Alias = "w";
Description = "Google search proxy.";
IconURL = "https://google.voronind.com/favicon.ico";
Method = "POST";
Name = "Whoogle";
PostData = "q={searchTerms}";
SuggestURLTemplate = "https://google.voronind.com/autocomplete?q={searchTerms}";
URLTemplate = "https://google.voronind.com/search?q=%{searchTerms}";
}
];
};
};
};
}

View file

@ -0,0 +1,3 @@
{ ... }: {
networking.firewall.enable = false;
}

6
module/common/Font.nix Normal file
View file

@ -0,0 +1,6 @@
{ pkgs, ... }: {
fonts.packages = with pkgs; [
(pkgs.callPackage ./applefont {})
(nerdfonts.override { fonts = [ "Terminus" ]; })
];
}

12
module/common/Git.nix Normal file
View file

@ -0,0 +1,12 @@
{ pkgs, ... }: {
programs.git = {
enable = true;
config = {
credential.helper = "store";
init.defaultBranch = "main";
pull.rebase = true;
push.autoSetupRemote = true;
rebase.autoStash = true;
};
};
}

3
module/common/Gtk.nix Normal file
View file

@ -0,0 +1,3 @@
{ environment, ... }: {
environment.etc.gtk.source = ./gtk;
}

59
module/common/Kernel.nix Normal file
View file

@ -0,0 +1,59 @@
{ pkgs, ... }: {
# Use latest kernel.
boot.kernelPackages = pkgs.linuxPackages_latest;
# Sysctl.
boot.kernel.sysctl = {
# Spoof protection.
"net.ipv4.conf.default.rp_filter" = 1;
"net.ipv4.conf.all.rp_filter" = 1;
# Packet forwarding.
"net.ipv4.ip_forward" = 1;
# "net.ipv6.conf.all.forwarding" = 1;
# MITM protection.
"net.ipv4.conf.all.accept_redirects" = 0;
"net.ipv6.conf.all.accept_redirects" = 0;
# Do not send ICMP redirects (we are not a router).
"net.ipv4.conf.all.send_redirects" = 0;
# Do not accept IP source route packets (we are not a router).
"net.ipv4.conf.all.accept_source_route" = 0;
"net.ipv6.conf.all.accept_source_route" = 0;
# Allow sysrq.
"kernel.sysrq" = 1;
# Protect filesystem links.
# "fs.protected_hardlinks" = 0;
# "fs.protected_symlinks" = 0;
# Specify ttl.
"net.ipv4.ip_default_ttl" = 65;
# Lynis config.
"kernel.core_uses_pid" = 1;
"kernel.kptr_restrict" = 2;
# IP hardening.
"net.ipv4.conf.all.log_martians" = 1;
"net.ipv4.conf.default.accept_redirects" = 0;
"net.ipv4.conf.default.accept_source_route" = 0;
"net.ipv4.conf.default.log_martians" = 0;
"net.ipv4.tcp_timestamps" = 0;
"net.ipv6.conf.default.accept_redirects" = 0;
# Increase file watchers.
"fs.inotify.max_user_instances" = 999999;
"fs.inotify.max_user_watches" = 999999;
"fs.inotify.max_user_event" = 999999;
# Disable ipv6.
"net.ipv6.conf.all.disable_ipv6" = 1;
"net.ipv6.conf.default.disable_ipv6" = 1;
"net.ipv6.conf.lo.disable_ipv6" = 1;
"net.ipv6.conf.eth0.disable_ipv6" = 1;
};
}

64
module/common/Ld.nix Normal file
View file

@ -0,0 +1,64 @@
{ pkgs, ... }: {
programs.nix-ld = {
enable = true;
package = pkgs.nix-ld;
libraries = with pkgs; [
# Add any missing dynamic libraries for unpackaged programs here, NOT in environment.systemPackages.
alsa-lib
at-spi2-atk
at-spi2-core
atk
cairo
cups
curl
dbus
expat
fontconfig
fontconfig
freetype
freetype
fuse3
gdk-pixbuf
glib
gtk3
icu
libGL
libappindicator-gtk3
libdrm
libglvnd
libglvnd
libnotify
libpulseaudio
libunwind
libusb1
libuuid
libxkbcommon
libxml2
mesa
nspr
nss
openssl
pango
pipewire
sqlite
stdenv.cc.cc
systemd
vulkan-loader
xorg.libX11
xorg.libXScrnSaver
xorg.libXcomposite
xorg.libXcursor
xorg.libXdamage
xorg.libXext
xorg.libXfixes
xorg.libXi
xorg.libXrandr
xorg.libXrender
xorg.libXtst
xorg.libxcb
xorg.libxkbfile
xorg.libxshmfence
zlib
];
};
}

15
module/common/Locale.nix Normal file
View file

@ -0,0 +1,15 @@
{ ... }: {
time.timeZone = "Europe/Moscow";
i18n.defaultLocale = "en_US.UTF-8";
i18n.extraLocaleSettings = {
LC_ADDRESS = "ru_RU.UTF-8";
LC_IDENTIFICATION = "ru_RU.UTF-8";
LC_MEASUREMENT = "ru_RU.UTF-8";
LC_MONETARY = "ru_RU.UTF-8";
LC_NAME = "ru_RU.UTF-8";
LC_NUMERIC = "ru_RU.UTF-8";
LC_PAPER = "ru_RU.UTF-8";
LC_TELEPHONE = "ru_RU.UTF-8";
LC_TIME = "ru_RU.UTF-8";
};
}

View file

@ -0,0 +1,4 @@
{ lib, ... }: {
networking.useDHCP = lib.mkDefault true;
networking.networkmanager.enable = true;
}

18
module/common/Nix.nix Normal file
View file

@ -0,0 +1,18 @@
{ environment, ... }: {
environment.variables.NIXPKGS_ALLOW_UNFREE = "1";
nixpkgs.config.allowUnfree = true;
nix.settings.auto-optimise-store = true;
nix.extraOptions = ''
experimental-features = nix-command flakes
keep-derivations = true
keep-outputs = true
min-free = ${toString (10 * 1024 * 1024 * 1024)}
'';
# max-free = ${toString (10 * 1024 * 1024 * 1024)}
# nix.gc = {
# automatic = true;
# dates = "weekly";
# options = "--delete-older-than 30d";
# persistent = true;
# };
}

58
module/common/Nvim.nix Normal file
View file

@ -0,0 +1,58 @@
{ environment, inputs, ... }: let
nvimSrc = "/etc/nvim/";
in {
environment.etc.nvim.source = ./nvim;
programs.neovim = {
enable = true;
viAlias = true;
vimAlias = true;
configure = {
customRC = ''
set runtimepath+=~/.cache/nvim,~/.cache/nvim/treesitter,${inputs.nvimTrouble},${inputs.nvimAlign},${inputs.nvimAutoclose},${inputs.nvimBufferline},${inputs.nvimCloseBuffers},${inputs.nvimDevicons},${inputs.nvimGitsigns},${inputs.nvimGruvbox},${inputs.nvimIndentoMatic},${inputs.nvimLspconfig},${inputs.nvimLualine},${inputs.nvimOllama},${inputs.nvimPlenary},${inputs.nvimSingleComment},${inputs.nvimTelescope},${inputs.nvimTodo},${inputs.nvimTokyonight},${inputs.nvimTree},${inputs.nvimTreesitter},${inputs.nvimWhichKey}
lua dofile("${nvimSrc}/key/Rekey.lua")
lua dofile("${nvimSrc}/key/Leader.lua")
lua dofile("${nvimSrc}/config/Autoread.lua")
lua dofile("${nvimSrc}/config/Etc.lua")
lua dofile("${nvimSrc}/config/Search.lua")
lua dofile("${nvimSrc}/config/Tab.lua")
lua dofile("${nvimSrc}/plugin/Filetree.lua")
lua dofile("${nvimSrc}/plugin/lsp/Rust.lua")
lua dofile("${nvimSrc}/plugin/lsp/Tex.lua")
lua dofile("${nvimSrc}/plugin/Bufferline.lua")
lua dofile("${nvimSrc}/plugin/Lualine.lua")
lua dofile("${nvimSrc}/plugin/Autoclose.lua")
lua dofile("${nvimSrc}/plugin/Gitsigns.lua")
lua dofile("${nvimSrc}/plugin/Trouble.lua")
lua dofile("${nvimSrc}/plugin/Tokyonight.lua")
lua dofile("${nvimSrc}/plugin/Gruvbox.lua")
lua dofile("${nvimSrc}/plugin/Closebuffers.lua")
lua dofile("${nvimSrc}/plugin/Telescope.lua")
lua dofile("${nvimSrc}/plugin/Todo.lua")
lua dofile("${nvimSrc}/plugin/Indent.lua")
lua dofile("${nvimSrc}/plugin/Align.lua")
lua dofile("${nvimSrc}/plugin/Treesitter.lua")
lua dofile("${nvimSrc}/plugin/Fold.lua")
lua dofile("${nvimSrc}/plugin/Ollama.lua")
lua dofile("${nvimSrc}/key/Autocomplete.lua")
lua dofile("${nvimSrc}/key/Buffer.lua")
lua dofile("${nvimSrc}/key/Comment.lua")
lua dofile("${nvimSrc}/key/Common.lua")
lua dofile("${nvimSrc}/key/Filetree.lua")
lua dofile("${nvimSrc}/key/Fold.lua")
lua dofile("${nvimSrc}/key/Gitsigns.lua")
lua dofile("${nvimSrc}/key/Lsp.lua")
lua dofile("${nvimSrc}/key/Navigation.lua")
lua dofile("${nvimSrc}/key/Ollama.lua")
lua dofile("${nvimSrc}/key/Sort.lua")
lua dofile("${nvimSrc}/key/Telescope.lua")
lua dofile("${nvimSrc}/key/Terminal.lua")
lua dofile("${nvimSrc}/key/Todo.lua")
lua dofile("${nvimSrc}/key/Trouble.lua")
lua dofile("${nvimSrc}/key/Update.lua")
lua dofile("${nvimSrc}/key/Whichkey.lua")
'';
};
};
}

56
module/common/Package.nix Normal file
View file

@ -0,0 +1,56 @@
{ pkgs, ... }: {
environment.systemPackages = with pkgs; [
appimage-run
binwalk
btop
calibre
coreutils
cryptsetup
curl
ddrescue
dxvk
ffmpeg
file
gamescope
gcc
gnome.gnome-tweaks
gnumake
gnused
imagemagick
jdk
jdk11
jdk19
jdk20
jellyfin-media-player
jq
lm_sensors
lshw
lsof
ltex-ls
mangohud
mpv
ncdu
nmap
parallel
parted
pv
ripgrep
scanmem
smartmontools
sqlite
steam-run
testdisk
tree
universal-android-debloater
ventoy
vkd3d
wget
wine64
wl-clipboard
yt-dlp
zip unzip
];
# Special packages.
programs.adb.enable = true;
}

3
module/common/Root.nix Normal file
View file

@ -0,0 +1,3 @@
{ specialArgs, ... }: {
users.users.root.hashedPassword = specialArgs.const.hashedPassword;
}

49
module/common/Ssh.nix Normal file
View file

@ -0,0 +1,49 @@
{ pkgs, ... }: {
environment.systemPackages = with pkgs; [ sshfs ];
programs.ssh.extraConfig = ''
Host dasha
HostName 192.168.1.7
User root
Port 22143
Host desktop
Hostname 192.168.1.3
User root
Port 22143
Host fmpmaven
Hostname 10.30.22.10
User root
Port 22
Host fsight
Hostname 10.30.217.25
User root
Port 22143
Host home
HostName 192.168.1.2
User root
Port 22143
Host laptop
Hostname 192.168.1.9
User root
Port 22143
Host pi
Hostname 192.168.1.6
User root
Port 22143
Host vpn
Hostname 194.113.233.38
User root
Port 22143
Host work
Hostname 192.168.1.5
User root
Port 22143
'';
}

32
module/common/Sshd.nix Normal file
View file

@ -0,0 +1,32 @@
{ ... }: {
services.openssh = {
enable = true;
allowSFTP = true;
ports = [ 22143 ];
listenAddresses = [
{
addr = "0.0.0.0";
port = 22143;
}
];
settings = {
AllowUsers = [ "root" ];
LoginGraceTime = "1m";
MaxAuthTries = 1;
MaxSessions = 10;
PermitRootLogin = "yes";
StrictModes = false;
UseDns = false;
UsePAM = true;
GSSAPIAuthentication = false;
HostbasedAuthentication = false;
KbdInteractiveAuthentication = true;
KerberosAuthentication = false;
PasswordAuthentication = true;
PermitEmptyPasswords = false;
PubkeyAuthentication = false;
};
};
}

4
module/common/Swap.nix Normal file
View file

@ -0,0 +1,4 @@
{ ... }: {
zramSwap.enable = true;
swapDevices = [ ];
}

26
module/common/Tmux.nix Normal file
View file

@ -0,0 +1,26 @@
{ ... }: {
imports = [
./tmux/Buffer.nix
./tmux/Environment.nix
./tmux/Pane.nix
./tmux/Session.nix
./tmux/Statusbar.nix
./tmux/Window.nix
];
programs.tmux = {
enable = true;
extraConfig = ''
# Remap <C-b> to <C-t>.
unbind-key C-b
set-option -g prefix C-t
bind-key C-t send-prefix
# Disable escape delay.
set -sg escape-time 0
# Reload config.
bind -n M-r source-file /etc/tmux.conf
'';
};
}

13
module/common/Users.nix Normal file
View file

@ -0,0 +1,13 @@
{ environment, ... }: {
users.mutableUsers = false;
environment.etc."user-dirs.dirs".text = ''
XDG_DESKTOP_DIR="$HOME/"
XDG_DOWNLOAD_DIR="$HOME/download"
XDG_TEMPLATES_DIR="$HOME/document/template"
XDG_PUBLICSHARE_DIR="$HOME/"
XDG_DOCUMENTS_DIR="$HOME/document"
XDG_MUSIC_DIR="$HOME/"
XDG_PICTURES_DIR="$HOME/media/picture"
XDG_VIDEOS_DIR="$HOME/media/video"
'';
}

View file

@ -0,0 +1,3 @@
{ environment, ... }: {
environment.etc.wallpaper.source = ./wallpaper;
}

View file

@ -0,0 +1,54 @@
{ lib, stdenv, fetchurl, p7zip }: let
pro = fetchurl {
url = "https://devimages-cdn.apple.com/design/resources/download/SF-Pro.dmg";
sha256 = "sha256-Mu0pmx3OWiKBmMEYLNg+u2MxFERK07BQGe3WAhEec5Q=";
};
compact = fetchurl {
url = "https://devimages-cdn.apple.com/design/resources/download/SF-Compact.dmg";
sha256 = "sha256-Mkf+GK4iuUhZdUdzMW0VUOmXcXcISejhMeZVm0uaRwY=";
};
mono = fetchurl {
url = "https://devimages-cdn.apple.com/design/resources/download/SF-Mono.dmg";
sha256 = "sha256-tZHV6g427zqYzrNf3wCwiCh5Vjo8PAai9uEvayYPsjM=";
};
ny = fetchurl {
url = "https://devimages-cdn.apple.com/design/resources/download/NY.dmg";
sha256 = "sha256-tn1QLCSjgo5q4PwE/we80pJavr3nHVgFWrZ8cp29qBk=";
};
in stdenv.mkDerivation {
name = "applefont";
dontUnpack = true;
nativeBuildInputs = [ p7zip ];
installPhase = let
unpackFont = dmg: dir: pkg: ''
7z x '${dmg}'
pushd '${dir}'
7z x '${pkg}'
7z x 'Payload~'
cp Library/Fonts/* $TMPDIR
popd
'';
in ''
${unpackFont pro "SFProFonts" "SF Pro Fonts.pkg"}
${unpackFont mono "SFMonoFonts" "SF Mono Fonts.pkg"}
${unpackFont compact "SFCompactFonts" "SF Compact Fonts.pkg"}
${unpackFont ny "NYFonts" "NY Fonts.pkg"}
mkdir -p $out/usr/share/fonts/{TTF,OTF}
mv $TMPDIR/*.otf $out/usr/share/fonts/OTF
mv $TMPDIR/*.ttf $out/usr/share/fonts/TTF
'';
meta = with lib; {
description = "Apple San Francisco, New York fonts.";
homepage = "https://developer.apple.com/fonts";
license = licenses.unfree;
meta.platforms = platforms.all;
};
}

View file

@ -0,0 +1,18 @@
# If not running interactively, don't do anything.
[[ "$-" != *i* ]] && return
# Src system bashrc.
[[ -f /etc/bashrc ]] && source /etc/bashrc
# Src custom modules.
for module in ${BASH_MODULE_PATH}/*.sh; do
source "${module}"
done
# Alias to reload.
function bashrc() {
source ${BASH_PATH}/Bashrc.sh
}
# Export all functions.
export -f $(find_function | tr '\n' ' ')

View file

@ -0,0 +1,16 @@
# Start an Android emulator.
# Default name is `main`.
# Usage: emulator [NAME]
function emulator() {
local name="${1}"
[[ "${name}" = "" ]] && name="main"
steam-run ${ANDROID_SDK_ROOT}/emulator/emulator -avd "${name}" &> /dev/null & disown
}
function _android_emulators() {
_autocomplete_first $(ls --classify ~/.android/avd/ | grep \/$ | sed -e "s/.avd\/$//")
}
complete -F _android_emulators emulator

View file

@ -0,0 +1,378 @@
export _archive_pattern="_[0-9]{12}-[[:alnum:]]{40}.t[xg]z$"
export _archive_pattern_fast="_[0-9]{12}-[[:alnum:]]{40}.tgz$"
# Archive directories.
# All directories by default.
# Supports .archiveignore exclude file.
# Usage: archive [DIRS]
function archive() {
local IFS=$'\n'
local targets=(${@})
[[ "${targets}" = "" ]] && targets=($(_ls_dir))
process() {
local date=$(_archive_date)
# Parse name.
local name=$(parse_pascal ${target})
# Exclude support.
local exclude=""
[[ -f ".archiveignore" ]] && exclude="--exclude-from=.archiveignore"
[[ -f "${target}/.archiveignore" ]] && exclude="--exclude-from=${target}/.archiveignore"
# create archive.
local hash=$(tar ${exclude} -c ${target} | pv -s $(/usr/bin/env du -sb ${target} | awk '{print $1}') | xz -9e | tee ${name}.txz | sha1sum | cut -d\ -f1)
# append hash to target name.
local new_name="${name}_${date}-${hash}.txz"
mv -- ${name}.txz ${new_name} && echo ${new_name}
}
_iterate_targets process ${targets[@]}
}
# Archive using multiple threads. Uses 75% of free RAM.
# All directories by default.
# Supports .archiveignore exclude file.
# Usage: archive_mt [DIRS]
function archive_mt() {
local IFS=$'\n'
local targets=(${@})
[[ "${targets}" = "" ]] && targets=($(_ls_dir))
process() {
local date=$(_archive_date)
# Parse name.
local name=$(parse_pascal ${target})
# Exclude support.
local exclude=""
[[ -f ".archiveignore" ]] && exclude="--exclude-from=.archiveignore"
[[ -f "${target}/.archiveignore" ]] && exclude="--exclude-from=${target}/.archiveignore"
# Determine memory limit.
local mem_free=$(_mem_free)
local mem_limit=$((mem_free*3/4))
# create archive.
local hash=$(tar ${exclude} -c ${target} | pv -s $(/usr/bin/env du -sb ${target} | awk '{print $1}') | xz -9e --threads=0 --memlimit=${mem_limit}MiB | tee ${name}.txz | sha1sum | cut -d\ -f1)
# append hash to target name.
local new_name="${name}_${date}-${hash}.txz"
mv -- ${name}.txz ${new_name} && echo ${new_name}
}
_iterate_targets process ${targets[@]}
}
# Archive directories with fast compression.
# All directories by default.
# Supports .archiveignore exclude file.
# Usage: archive_fast [DIRS]
function archive_fast() {
local IFS=$'\n'
local targets=("${@}")
[[ "${targets}" = "" ]] && targets=($(_ls_dir))
process() {
# Start timestamp.
local date=$(_archive_date)
# Parse name.
local name=$(parse_pascal "${target}")
# Exclude support.
local exclude=""
[[ -f ".archiveignore" ]] && exclude="--exclude-from=.archiveignore"
[[ -f "${target}/.archiveignore" ]] && exclude="--exclude-from=${target}/.archiveignore"
# create archive.
local hash=$(tar ${exclude} -c "${target}" | pv -s $(/usr/bin/env du -sb "${target}" | awk '{print $1}') | gzip -1 | tee "${name}".tgz | sha1sum | cut -d\ -f1)
# append hash to target name.
local new_name="${name}_${date}-${hash}.tgz"
mv -- "${name}".tgz ${new_name} && echo ${new_name}
}
_iterate_targets process ${targets[@]}
}
# Check archives integrity.
# Checks all archives by default.
# Usage: archive_check [FILES]
function archive_check() {
local IFS=$'\n'
local targets=(${@})
[[ "${targets}" = "" ]] && targets=($(_ls_archive))
process() {
_archive_check "${target}"
}
_iterate_targets process ${targets[@]}
}
# Delete old versions of an archive.
# All archives with 1 version by default.
# Usage: archive_prune [NAME] [VERSIONS]
function archive_prune() {
local IFS=$'\n'
local targets=(${1})
local versions=${2}
[[ "${targets}" = "" ]] && targets=($(_archive_names))
[[ "${versions}" = "" ]] && versions=1
if [[ ${#} -gt 2 ]]; then
help archive_prune
return 2
fi
process() {
local prune=($(ls | grep -E "^${target}${_archive_pattern}" | sort -r | sed -e "1,${versions}d"))
for archive in ${prune[@]}; do
rm -- "${archive}" && echo "${archive}"
done
}
_iterate_targets process ${targets[@]}
}
# Delete specified or all archive files.
# Usage: archive_rm [FILES]
function archive_rm() {
local IFS=$'\n'
local targets=(${@})
[[ "${targets}" = "" ]] && targets=($(_ls_archive))
process() {
rm -- "${target}" && echo "${target}"
}
_iterate_targets process ${targets[@]}
}
# Recompress previously created archive_fast with better compression.
# Usage: archive_xz [FILES]
function archive_xz() {
local IFS=$'\n'
local targets=(${@})
[[ "${targets}" = "" ]] && targets=$(_ls_archive_fast)
process() {
local data=($(_archive_parse "${target}"))
local tmp="${data[0]}.txz"
# Check that old format.
if [[ "${data[3]}" != "tgz" ]]; then
_error "Not in .tgz format!"
return 1
fi
# Check integrity.
_archive_check "${target}" || return 1
# Recompress.
local hash=$(pv "${target}" | gzip -d | xz -9e | tee "${tmp}" | sha1sum | cut -d\ -f1)
# Rename.
local new_name="${data[0]}_${data[1]}-${hash}.txz"
mv -- ${tmp} ${new_name} && rm ${target} && echo ${new_name}
}
_iterate_targets process ${targets[@]}
}
# Rename archives.
# If no name specified, it simplifies archive's name.
# If no archives specified, apply to all archives.
# Usage: archive_name [ARCHIVE] [NAME]
function archive_name() {
local IFS=$'\n'
local targets="${1}"
local name="${2}"
[[ "${targets}" = "" ]] && targets=($(_ls_archive))
process() {
# simplify name by default.
if [[ "${name}" = "" || ${count} -gt 1 ]]; then
name="${target%_*}"
name="$(parse_pascal ${name})"
fi
# remove old name.
local data="${target##*_}"
local new_name="${name}_${data}"
# check for the same name.
[[ "${target}" = "${new_name}" ]] && return 0
# check for existing target.
if [[ -f "${new_name}" ]]; then
_error "${new_name}: Already exists!"
return 1
fi
# rename.
mv -- ${target} ${new_name} && echo ${new_name}
}
_iterate_targets process ${targets[@]}
}
# Extract previously created archive with checksum validation.
# Usage: unarchive [FILES]
function unarchive() {
local IFS=$'\n'
local targets=(${@})
[[ "${targets}" = "" ]] && targets=$(_ls_archive)
process() {
# Validate.
# _archive_check "${target}" || return 1
# Extract.
case "${target##*.}" in
"txz")
pv ${target} | xz -d | tar -xf -
;;
"tgz")
pv ${target} | gzip -d | tar -xf -
;;
esac
}
_iterate_targets process ${targets[@]}
}
# Change archive's filesystem time to match creation date.
# Usage: archive_touch [FILES]
function archive_touch() {
local IFS=$'\n'
local targets=(${@})
[[ "${targets}" = "" ]] && targets=$(_ls_archive)
process() {
local data=($(_archive_parse "${target}"))
local date=${data[1]}
touch -t ${date} -- ${target}
}
_iterate_targets process ${targets[@]}
}
# Parse archive file name to get: name, date, hash and format.
# Usage: _archive_parse <FILENAME>
function _archive_parse() {
local input="${1}"
local name="${input%_*}"
local format="${input##*.}"
local data="${input##*_}"; data="${data%.*}"
local date="${data%%-*}"
local hash="${data##*-}"
echo "${name}"
echo "${date}"
echo "${hash}"
echo "${format}"
}
# Autocomplete for archive_name function.
# First arg is the archives list, second one is selected archive's current name.
function _comp_archive_name() {
local IFS=$'\n'
COMPREPLY=()
local cur="${COMP_WORDS[COMP_CWORD]}"
local prev="${COMP_WORDS[COMP_CWORD-1]}"
local command="${COMP_WORDS[0]}"
if [[ "${prev}" = "${command}" ]]; then
COMPREPLY=( $(compgen -W "$(ls | grep -E ${_archive_pattern})" -- ${cur}) )
return 0
else
local data=($(_archive_parse ${prev}))
local name="${data[0]}"
COMPREPLY=( $(compgen -W "${name}" -- ${cur}) )
return 0
fi
}
# Autocomplete with archives in current dir.
function _comp_archive_grep() {
_autocomplete_grep ${_archive_pattern}
}
# Autocomplete with fast archives in current dir.
function _comp_archive_grep_fast() {
_autocomplete_grep ${_archive_pattern_fast}
}
# Get date for a new archive.
function _archive_date() {
date +%Y%m%d%H%M
}
# Get names of all archives.
function _archive_names() {
local IFS=$'\n'
local archives=($(_ls_archive))
local names=()
for archive in ${archives[@]}; do
local data=($(_archive_parse ${archive}))
names+=(${data[0]})
done
# Remove copies.
names=($(printf '%s\n' "${names[@]}" | sort -u))
printf '%s\n' "${names[@]}"
}
# Autocomplete with names of all archives.
function _comp_archive_names() {
_autocomplete_first $(_archive_names)
}
# Check if file is an archive.
function _is_archive() {
local out=$(echo "${*}" | grep -E ${_archive_pattern})
[[ "${out}" != "" ]]
}
# List all archives.
function _ls_archive() {
ls | grep -E ${_archive_pattern}
}
# List fast archives.
function _ls_archive_fast() {
ls | grep -E ${_archive_pattern_fast}
}
# Filter input for archives only.
function _filter_archive() {
grep -E ${_archive_pattern}
}
function _archive_check() {
# extract hash from name.
local data=($(_archive_parse ${target}))
local saved=${data[2]}
# calculate actual hash.
local actual=$(pv ${target} | sha1sum | cut -d\ -f1)
# compare hashes.
[[ "${actual}" = "${saved}" ]]
}
complete -o filenames -F _comp_archive_grep archive_check unarchive archive_rm archive_touch
complete -o filenames -F _comp_archive_grep_fast archive_xz
complete -o filenames -F _comp_archive_name archive_name
complete -o filenames -F _comp_archive_names archive_prune

View file

@ -0,0 +1,9 @@
# Ask general AI.
# Usage: ask <QUERY>
function ask() {
curl http://localhost:11434/api/generate -d "{
\"model\": \"mistral\",
\"prompt\":\"${*}\"
}" 2> /dev/null | parallel -j1 -- "echo {} | jq -r .response | tr -d '\n'"
echo
}

View file

@ -0,0 +1,83 @@
# Bash autocomplete.
# There are also options like -o nospace. see man for more info.
# Usage: _foo() { _autocomplete "{foo,bar}" } ; complete -F _foo foo
function _autocomplete() {
local IFS=$'\n'
local commands="${*}"
COMPREPLY=()
local cur="${COMP_WORDS[COMP_CWORD]}"
local prev="${COMP_WORDS[COMP_CWORD-1]}"
local command="${COMP_WORDS[0]}"
COMPREPLY=( $(compgen -W "${commands}" -- ${cur}) )
return 0
}
# Autocomplete only first argument.
function _autocomplete_first() {
local IFS=$'\n'
local commands="${*}"
COMPREPLY=()
local cur="${COMP_WORDS[COMP_CWORD]}"
local prev="${COMP_WORDS[COMP_CWORD-1]}"
local command="${COMP_WORDS[0]}"
if [[ "${prev}" = "${command}" ]]; then
COMPREPLY=( $(compgen -W "${commands}" -- ${cur}) )
return 0
fi
}
# Autocomplete only first argument and the rest with files.
function _autocomplete_first_ls() {
local IFS=$'\n'
local commands="${*}"
COMPREPLY=()
local cur="${COMP_WORDS[COMP_CWORD]}"
local prev="${COMP_WORDS[COMP_CWORD-1]}"
local command="${COMP_WORDS[0]}"
if [[ "${prev}" = "${command}" ]]; then
COMPREPLY=( $(compgen -W "${commands}" -- ${cur}) )
return 0
else
COMPREPLY=( $(compgen -W "$(ls)" -- ${cur}) )
return 0
fi
}
# Autocomplete by grepping file names.
function _autocomplete_grep() {
local IFS=$'\n'
COMPREPLY=()
local pattern="${1}"
local cur="${COMP_WORDS[COMP_CWORD]}"
local prev="${COMP_WORDS[COMP_CWORD-1]}"
local command="${COMP_WORDS[0]}"
COMPREPLY=( $(compgen -W "$(ls | grep -E ${pattern})" -- ${cur}) )
return 0
}
# Autocomplete nested program.
function _autocomplete_nested() {
# local IFS=$'\n'
local cur prev words cword split i
_init_completion -s || return
for ((i = 1; i <= cword; i++)); do
if [[ ${words[i]} != -* ]]; then
local PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin
local root_command=${words[i]}
_command_offset ${i}
return
fi
done
}

View file

@ -0,0 +1,12 @@
# Print current battery charge in percents.
function battery_charge() {
head -c -1 /sys/class/power_supply/BAT*/capacity
echo '%'
}
# Get battery's info.
function battery_info() {
local IFS=$'\n'
local battery=("$(upower --enumerate | grep battery_BAT)")
upower -i "${battery[0]}"
}

View file

@ -0,0 +1,70 @@
# Install Editorconfig file (with tabs) in current directory.
function bootstrap_editorconfig() {
echo "\
[*]
end_of_line = lf
charset = utf-8
indent_style = tab
insert_final_newline = true
trim_trailing_whitespace = true
" > .editorconfig
}
# Install Editorconfig file (with specified spaces, 8 by default) in current directory.
# Usage: bootstrap_editorconfig_space [AMOUNT]
function bootstrap_editorconfig_space() {
local spaces="${1}"
[[ "${spaces}" = "" ]] && spaces=8
echo "\
[*]
end_of_line = lf
charset = utf-8
indent_style = space
indent_size = ${spaces}
insert_final_newline = true
trim_trailing_whitespace = true
" > .editorconfig
}
# Install nixos to specified drive. To be run from Live ISO.
# Usage: bootstrap_nixos <DRIVE> [HOST]
function bootstrap_nixos() {
local target="${1}"
local host="${2}"
if [[ "${target}" = "" ]]; then
help bootstrap_nixos
return 2
fi
# Create partitions.
parted -s "${target}" mktable gpt
parted -s "${target}" mkpart primary 0% 512MB
parted -s "${target}" mkpart primary 512MB 100%
parted -s "${target}" name 1 NIXBOOT
parted -s "${target}" name 2 NIXROOT
parted -s "${target}" set 1 esp on
# Format.
mkfs.fat -F 32 /dev/disk/by-partlabel/NIXBOOT
mkfs.ext4 -F /dev/disk/by-partlabel/NIXROOT
# Mount.
mount /dev/disk/by-partlabel/NIXROOT /mnt
mkdir /mnt/boot
mount /dev/disk/by-partlabel/NIXBOOT /mnt/boot
# Generate config.
nixos-generate-config --root /mnt
# Install.
cd /mnt
if [[ "${host}" = "" ]]; then
_warn "Warning: Installing basic system."
nixos-install
else
_info "Installing ${host}..."
nixos-install --no-root-password --no-channel-copy --flake "${_nix_system_config}#${host}"
fi
}

View file

@ -0,0 +1,59 @@
# CD (back to) directory.
# Goes to the exact-match dir first. If no exact match found, it finds first directory that contains the input (case-insensitive).
# Usage: cdd <DIR>
function cdd() {
local target="${1}"
if [[ "${target}" = "" ]]; then
help cdd
return 2
fi
local array=($(_cdd_directories))
local result
# Check for exact match ELSE look for containing.
if _contains ${target} ${array[@]}; then
local current="${PWD%/*}"
result="${current%\/$target\/*}/${target}"
else
# Make search case-insensitive.
shopt -s nocasematch
# Find dir name that contains input.
local found=1
for (( idx=${#array[@]}-1 ; idx>=0 ; idx-- )); do
dir="${array[idx]}"
[[ "${dir}" =~ "${target}" ]] && found=0
[[ ${found} = 0 ]] && result="/${dir}${result}"
done
# Clean-up???
shopt -u nocasematch
fi
# Go there!
if [[ "${result}" != "" ]]; then
echo "${result}"
cd "${result}"
else
return 1
fi
}
# Get list of all parent dirs.
function _cdd_directories() {
local array
IFS='/' read -r -a array <<< "${PWD}"
array=("${array[@]:1}")
unset array[-1]
printf "%s\n" "${array[@]}"
}
function _comp_cdd() {
local IFS=$'\n'
local dirs=($(_cdd_directories))
_autocomplete_first ${dirs[@]}
}
complete -o nosort -o filenames -F _comp_cdd cdd

View file

@ -0,0 +1,83 @@
# Save file checksums.
# For file with a name `file` it will create a new file called `.file.sha1` with hash in it.
# All files by default.
# Usage: checksum_create [FILES]
function checksum_create() {
local IFS=$'\n'
local targets=(${@})
[[ "${targets}" = "" ]] && targets=($(_ls_file))
process() {
local hashfile=".${target#./}.sha1"
# Skip if hash exists.
[[ -f "${hashfile}" ]] && return 0
# Calculate hash.
pv ${target} | sha1sum > ${hashfile}
}
_iterate_targets process ${targets[@]}
}
# Check stored values against actual files.
# All files by default.
# Usage: checksum_check [FILES]
function checksum_check() {
local IFS=$'\n'
local targets=(${@})
[[ "${targets}" = "" ]] && targets=($(_ls_file))
process() {
local hashfile=".${target#./}.sha1"
# Skip if hash doesn't exist.
[[ -f "${hashfile}" ]] || { _iterate_skip "No hash found."; return 0; }
# Calculate hash.
local stored=$(cat "${hashfile}" | cut -d\ -f1)
local actual=$(pv "${target}" | sha1sum | cut -d\ -f1)
if [[ "${stored}" != "${actual}" ]]; then
_error "Failed."
return 1
fi
}
_iterate_targets process ${targets[@]}
}
# Calculate hashes for all files recursively and store in a file called `checksum.sha1`.
function checksum() {
find -type f | parallel -j $(_core_count) -- sha1sum {} >> checksum.sha1
}
# Create checksum for a file.
# Usage: _checksum_create <FILE>
function _checksum_create() {
local path="${1%/*}"
local name="${1##*/}"
sha1sum "${path}/${name}" > "${path}/.${name}.sha1"
}
# Check checksum for a file.
# Usage: _checksum_check <FILE>
function _checksum_check() {
local file="${1##*\ \ }"
local stored="${1%%\ \ *}"
# Skip if no file.
[[ -f "${file}" ]] || return 0
# Check file hash.
local actual=$(sha1sum "${file}")
actual="${actual%%\ \ *}"
# Compare values.
if [[ "${stored}" != "${actual}" ]]; then
_error "${file}: Failed."
return 1
fi
return 0
}

View file

@ -0,0 +1,5 @@
# Add executable flag to file.
# Usage: x <FILES>
function x() {
chmod +x -- "${@}"
}

View file

@ -0,0 +1,24 @@
# Collection of available CLI colors.
# They may differ depending on the terminal used.
# Colors with 'b' prefix are bold colors.
export color_default="\033[0m"
export color_blue="\033[0;34m"
export color_bblue="\033[1;34m"
export color_cyan="\033[0;36m"
export color_bcyan="\033[1;36m"
export color_green="\033[0;32m"
export color_bgreen="\033[1;32m"
export color_purple="\033[0;35m"
export color_bpurple="\033[1;35m"
export color_red="\033[0;31m"
export color_bred="\033[1;31m"
export color_white="\033[0;37m"
export color_bwhite="\033[1;37m"
export color_yellow="\033[0;33m"
export color_byellow="\033[1;33m"
# Print all available colors with their names colored in corresponding color.
function color_test() {
echo -e "${color_default}color_default\n${color_blue}color_blue\n${color_bblue}color_bblue\n${color_cyan}color_cyan\n${color_bcyan}color_bcyan\n${color_green}color_green\n${color_bgreen}color_bgreen\n${color_purple}color_purple\n${color_bpurple}color_bpurple\n${color_red}color_red\n${color_bred}color_bred\n${color_white}color_white\n${color_bwhite}color_bwhite\n${color_yellow}color_yellow\n${color_byellow}color_byellow"
}

View file

@ -0,0 +1,80 @@
# Attach/create container box in current directory with specified name.
# By default uses current dir name.
# Usage: ca [NAME]
function ca() {
local name="${1}"
# Set default name.
# [[ "${name}" = "" ]] && name="main"
[[ "${name}" = "" ]] && name=$(parse_alnum "${PWD##*/}")
# Append box prefix.
name="box-${name}"
# Create container.
docker run \
--privileged \
-d -it \
-h "${HOSTNAME}${name#box}" --name "${name}" \
--workdir /data \
-e XDG_RUNTIME_DIR=/tmp \
-e WAYLAND_DISPLAY=${WAYLAND_DISPLAY} \
-v ${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}:/tmp/${WAYLAND_DISPLAY} \
-v ${PWD}:/data \
-v ${HOME}:/root \
debian:latest bash -c bash &> /dev/null
# Attempt to start container.
docker start "${name}" &> /dev/null
# Attach to running container.
docker attach "${name}"
}
# Remove container box with specified name.
# By default uses current dir name.
# Usage: ck [NAME]
function ck() {
local name="${1}"
# Set default name.
[[ "${name}" = "" ]] && name=$(parse_alnum "${PWD##*/}")
# Append box prefix.
name="box-${name}"
# Kill container.
docker kill "${name}" &> /dev/null
docker rm "${name}" &> /dev/null
}
# Remove all container boxes.
function cka() {
local IFS=$'\n'
local boxes=$(_get_boxes)
for box in ${boxes[@]}; do
ck "${box}"
done
}
# List all container boxes.
function cl() {
_get_boxes
}
# Print all boxes.
function _get_boxes() {
local IFS=$'\n'
local boxes=$(docker ps -a | grep "box-" | sed -e "s/.*box-//")
[[ "${boxes[@]}" != "" ]] && echo "${boxes[@]}" || true
}
# Autocomplete with boxes.
function _comp_get_boxes() {
local IFS=$'\n'
_autocomplete_first $(_get_boxes)
}
complete -F _comp_get_boxes ca ck

View file

@ -0,0 +1,9 @@
# Copy stdin to system clipboard. *Example:* `echo hi \| copy`.
function copy() {
wl-copy
}
# Paste system clipboard to stdout. *Example:* `paste > file.txt`.
function paste() {
wl-paste
}

View file

@ -0,0 +1,24 @@
# Replaces default cp with rsync.
# Usage: rcp <FROM> <TO>
function rcp() {
rsync -ahP --chmod=u+w "${@}"
}
# Copy and also merge all changes (delete dst files that do not exist in src).
# Usage: rcp_merge <FROM> <TO>
function rcp_merge() {
rsync -ahP --chmod=u+w --delete "${@}"
}
# Copy by creating hardlinks.
# Works for directories, too.
# Usage: cp_link <FROM> <TO>
function cp_link() {
/usr/bin/env cp -lr "${@}"
}
# Print output of cp_merge without writing anything.
# Usage: rcp_test <FROM> <TO>
function rcp_test() {
rsync -ahP --chmod=u+w --delete -n "${@}"
}

View file

@ -0,0 +1,9 @@
# Print today date in yyyyMMdd format.
function today() {
date +%Y%m%d
}
# Current day of week number.
function dow() {
date +%u
}

View file

@ -0,0 +1,16 @@
export _gdconf_path="${HOME}/.config/linux/Gnome.dconf"
# Load Gnome settings.
function dconf_load() {
sed -i -e s/voronind/$(whoami)/g ${_gdconf_path} ; dconf load / < ${_gdconf_path}
}
# Dump Gnome settings into the file.
# Default name is `gnome.dconf`.
# Do this before changing settings and after, an then run `diff` to find out what to add to the main `gnome.dconf`.
# Usage: dconf_save [FILE]
function dconf_save() {
local name="${1}"
[[ "${name}" = "" ]] && name="gnome.dconf"
dconf dump / > "${name}"
}

View file

@ -0,0 +1,11 @@
# Show only physical drives info.
function pdf() {
df --si | sed -e '1p' -e '/^\/dev\//!d'
}
# Show total size in SI.
# Current dir by default.
# Usage: tdu [DIRS]
function tdu() {
du -sh --si "${@}"
}

View file

@ -0,0 +1,15 @@
# Create/Attach to the box.
# Uses name `main` by default.
# Usage: da [BOX]
function da() {
local name="${1}"
[[ "${name}" = "" ]] && name="main"
# if [[ "${name}" = "" ]]; then
# help da
# return 2
# fi
# --user 0 is required for rootless docker.
distrobox enter -a '--user=0' "${name}"
}

View file

@ -0,0 +1,53 @@
# Generate a markdown file with all the help info.
# Outputs to `~/.doc/Bash.md`.
function doc_bash() {
local IFS=$'\n'
local file="${HOME}/.doc/Bash.md"
# Print title.
echo "# Bash reference file." > "${file}"
echo >> "${file}"
# Print help info.
echo "To get help with usage info run:" >> "${file}"
echo >> "${file}"
echo '```text' >> "${file}"
echo '$ help <COMMAND>' >> "${file}"
echo >> "${file}"
echo "or" >> "${file}"
echo >> "${file}"
echo '$ h <COMMAND>' >> "${file}"
echo '```' >> "${file}"
echo >> "${file}"
# Fill with data.
for module in $(find_module); do
# Skip if no functions.
[[ "$(find_function ${module} | grep -v ^_)" = "" ]] && continue
# Print module title.
echo "## ${module^}." >> "${file}"
echo >> "${file}"
# Print table title.
echo "Command|Description" >> "${file}"
echo "---|---" >> "${file}"
for fun in $(find_function ${module}); do
# Skip private functions.
[[ "${fun}" =~ ^_.* ]] && continue
# Parse help info.
local desc="$(help ${fun} | grep -v Usage\: | tr '\n' ' ')"
local usage="$(help ${fun} | grep Usage\: | sed -e s\/Usage\:\ \/\/)"
# Use function name if no usage info available.
[[ "${usage}" = "" ]] && usage="${fun}"
# Write to file.
[[ "${desc}" != "" ]] && echo "\`${usage}\`|${desc}" >> "${file}"
done
echo >> "${file}"
done
}

View file

@ -0,0 +1,95 @@
# Show container's volumes.
# Usage: docker_volumes <CONTAINER>
function docker_volumes() {
docker inspect -f '{{ .Mounts }}' "${@}"
}
# Check if any container exited.
function docker_health() {
docker ps -a | grep Exited
}
# Find out container's IP address.
# Usage: docker_ip <CONTAINER>
function docker_ip() {
docker inspect -f '\''{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'\' "${1}" | sed "s/^.//" | sed "s/.$//"
}
# Update all docker images.
function docker_update() {
docker images --format "{{.Repository}}:{{.Tag}}" | xargs -L1 docker pull
}
# Docker compose shortcut.
function dc() {
docker compose "${@}"
}
# Docker compose up.
# Usage: dcu [SERVICES]
function dcu() {
docker compose up -d "${@}"
}
# Docker compose down.
# Usage: dcd [SERVICES]
function dcd() {
docker compose down "${@}"
}
# Docker compose pull.
# Usage: dcp [SERVICES]
function dcp() {
docker compose pull "${@}"
}
# Docker compose logs.
# Usage: dcl [SERVICES]
function dcl() {
docker compose logs -f "${@}"
}
# Docker compose restart.
# Usage: dcr [SERVICES]
function dcr() {
docker compose restart "${@}"
}
# Docker compose stop.
# Usage: dcs [SERVICES]
function dcs() {
docker compose stop "${@}"
}
# Docker compose down & up specified services.
# Usage: dcdu [SERVICES]
function dcdu() {
dcd "${@}"
dcu "${@}"
}
# Docker compose pull & up specified services.
# Usage: dcpu [SERVICES]
function dcpu() {
dcp "${@}"
dcu "${@}"
}
# Docker compose up & attach to logs for specified services.
# Usage: dcul [SERVICES]
function dcul() {
dcu "${@}" && dcl "${@}"
}
# Autocomplete with available services.
function _dc_services() {
_autocomplete "$(docker compose config --services 2> /dev/null)"
}
# Autocomplete with available container names.
function _dc_containers() {
_autocomplete "$(docker ps --format "\""{{.Names}}"\"")"
}
complete -F _dc_services dcu dcd dcp dcl dcul dcdu dcr dcs dcpu
complete -F _dc_containers docker_volumes docker_ip

View file

@ -0,0 +1,39 @@
# Burn specified iso file to DVD.
# Usage: dvd_burn_iso <FILE.iso>
function dvd_burn_iso() {
local iso="${1}"
if [[ "${iso}" = "" ]]; then
help dvd_burn_iso
return 2
fi
growisofs -dvd-compat -speed=8 -use-the-force-luke=tty -Z /dev/sr0="${iso}"
}
# Burn specified iso file to CD.
# Usage: cd_burn_iso <FILE.iso>
function cd_burn_iso() {
local iso="${1}"
if [[ "${iso}" = "" ]]; then
help cd_burn_iso
return 2
fi
wodim speed=8 -tao dev=/dev/sr0 "${iso}"
}
# Burn specified audio files to CD.
# Usage: cd_burn_audio <FILES.wav>
function cd_burn_audio() {
if [[ "${*}" = "" ]]; then
help cd_burn_audio
return 2
fi
cdrecord -v dev=/dev/sr0 speed=8 -audio -pad "${*}"
}
# Spawn Nix shell with required tools.
function dvd_shell() {
NIX_SHELL="dvd" tmpshell dvdplusrwtools cdrkit
}

View file

@ -0,0 +1,94 @@
# Mux audio into containers. File names in sound and current dirrectories must match.
# Usage: ffmpeg_mux_audio <SOUND> <OUTPUT DIR>
function ffmpeg_mux_audio() {
if [[ "${1}" = "" ]]; then
help ffmpeg_mux_audio
return 2
fi
for file in *; do ffmpeg -i "$file" -i "$1"/"$file" -c copy -map 0:v:0 -map 1:a:0 -shortest "$2"/"$file"; done
}
# Mux cover into music file.
# Usage: ffmpeg_mux_cover <FORMAT> <COVER>
function ffmpeg_mux_cover() {
if [[ "${1}" = "" ]]; then
help ffmpeg_mux_cover
return 2
fi
local format="${1}"
local cover="${2}"
mkdir out
case "${format}" in
# "mka"|"mkv")
# for file in *.${format}; do
# ffmpeg -i "${file}" -attach "${cover}" -map 0 -c copy -metadata:s:t mimetype="image/${cover##*.}" -metadata:s:t:0 filename="cover.${cover##*.}" "./out/${file}" || return 1
# done
# ;;
*)
for file in *.${format}; do
ffmpeg -i "${file}" -i "${cover}" -map 0 -map 0:-v? -map 1 -codec copy -metadata:s:v title="Album cover" -metadata:s:v comment="Cover (front)" -disposition:v attached_pic ./out/"${file}" || return 1
done
;;
esac
mv out/* .
rm -d out/ && rm "${2}"
}
# Generate music metadata from directory structure.
# Top dir is the Artist name like this: `The_Beatles`.
# Next are albums like this: `2010_My_love`.
# Inside are songs like this: `01_sample.flac`.
# Usage: ffmpeg_music_meta <FORMAT>
function ffmpeg_music_meta() {
if [[ "${1}" = "" ]]; then
help ffmpeg_music_meta
return 2
fi
local format="${1}"
ls *.${format} &> /dev/null || return 1
local artist="${PWD%/*}"; artist="${artist##*/}"; artist="${artist//_/ }"
local album="${PWD##*/}"; album="${album#*_}"; album="${album//_/ }"
local year="${PWD##*/}"; year="${year%%_*}"
# local total=$(ls *.${format} | wc -l)
mkdir out
for file in *.${format}; do
local track="${file%%_*}"; track=$((10#${track})); [[ "${track}" = "" ]] && track=0
local title="${file#*_}"; title="${title%.*}"; title="${title//_/ }"
# echo "${artist}; ${album}; ${year}; ${track}; ${title}"
# TODO: make it format-specific.
ffmpeg -i "${file}" -map 0 -c copy -metadata "artist=${artist}" -metadata "album_artist=${artist}" -metadata "album=${album}" -metadata "date=${year}" -metadata "year=${year}" -metadata "date_released=${year}" -metadata "track=${track}" -metadata "part_number=${track}" -metadata "title=${title}" ./out/"${file}" || return 1
done
mv out/* .
rm -d out/
}
# Get video FPS.
function _ffprobe_fps() {
local fps=$(ffprobe -v 0 -of csv=p=0 -select_streams v:0 -show_entries stream=r_frame_rate "${1}")
[[ "${fps}" = "" ]] && fps=30 || fps=$((fps))
echo "${fps}"
}
# Get recommended keyframe interval for a file.
_ffprobe_keyint() {
local fps=$(_ffprobe_fps "${1}")
echo $((fps*5))
}
# Get audio bitrage. 128 by default.
function _ffprobe_ba() {
local ba=$(ffprobe -v error -select_streams a:0 -show_entries stream=bit_rate -of default=noprint_wrappers=1:nokey=1 "${1}")
[[ "${ba}" != "N/A" ]] && echo $((ba/1024)) || echo 128
}

View file

@ -0,0 +1,23 @@
# Open file/dir in GUI.
# Usage: o <FILE>
function o() {
xdg-open "${@}"
}
# Play media file from CLI. All files by default.
# Usage: play [FILE]
function play() {
local targets=${*}
[[ "${targets}" = "" ]] && targets=$(_ls_file)
mpv --no-video ${targets}
}
# Play media files shuffled from CLI. All files by default.
# Usage: play_shuffle [FILE]
function play_shuffle() {
local targets=${*}
[[ "${targets}" = "" ]] && targets=$(_ls_file)
mpv --no-video --shuffle ${targets}
}

View file

@ -0,0 +1,26 @@
# Find all file extensions.
function find_ext() {
local types=($(find -type f | sed -e "s/.*\///" -e "s/^\.//" -e "/\./!d" -e "s/.*\.//"))
echo "${types[@]}" | tr ' ' '\n' | sort -u
}
# Find all modules.
function find_module() {
ls "${BASH_MODULE_PATH}" | sed -e "s/.sh$//"
}
# Find all module functions.
# Functions from all modules by default.
# Usage: find_function [MODULE]
function find_function() {
local module="${1}"
[[ "${module}" = "" ]] && module="*"
cat "${BASH_MODULE_PATH}"/${module}.sh | grep "^function.*()" | sed -e "s/^function //" -e "s/().*//"
}
# Autocomplete with module.
_find_module() {
_autocomplete_first $(find_module)
}
complete -F _find_module find_function

View file

@ -0,0 +1,66 @@
# Fix when ethernet mistakenly detects 100 Mb instead of 1000 Mb.
# SPEED is one of 10/100/1000 etc.
# Usage: fix_ethernet_speed <DEVICE> <SPEED>
function fix_ethernet_speed() {
local device="${1}"
local speed="${2}"
if [[ "${device}" = "" || "${speed}" = "" ]]; then
help fix_ethernet_speed
return 2
fi
ethtool -s "${device}" speed "${speed}"
}
# Fix nautilus after typing wrong sftp password.
function fix_files_sftp() {
secret-tool clear protocol sftp
}
# Delete lost Gradle lock files.
function fix_gradle_lock() {
cd "${HOME}/.gradle" && find -type f | grep \\.lock$ | xargs -- rm
cd -
}
# Fix Gnome's broken RDP ffs.
# Usage: fix_gnome_rdp <PASSWORD>
function fix_gnome_rdp() {
local user="${USERNAME}"
local password="${1}"
# Check params.
if [[ "${password}" = "" ]]; then
help fix_gnome_rdp
return 2
fi
# Unlock keyring. PROTIP: Disable password for it in password manager.
pkill -9 -f gnome-keyring-daemon
echo -n "${user}" | gnome-keyring-daemon --unlock
# Generate keys.
cd /tmp
openssl genrsa -out rdp-tls.key 4096
openssl req -new -key rdp-tls.key -subj "/C=US" | openssl x509 -req -days 730 -signkey rdp-tls.key -out rdp-tls.crt
mkdir -p "${HOME}/.local/share/gnome-remote-desktop/"
mv rdp-tls.key rdp-tls.crt "${HOME}/.local/share/gnome-remote-desktop/"
# Configure RDP.
grdctl rdp set-tls-cert "${HOME}/.local/share/gnome-remote-desktop/rdp-tls.crt"
grdctl rdp set-tls-key "${HOME}/.local/share/gnome-remote-desktop/rdp-tls.key"
grdctl rdp set-credentials "${user}" "${password}"
grdctl rdp disable-view-only
# Start service.
grdctl rdp enable
systemctl --user start gnome-remote-desktop.service
# Show status.
grdctl status --show-credentials
systemctl --user status gnome-remote-desktop.service
# Show extra info.
_warn "You may need to manually restart Desktop sharing via Gnome Settings."
}

View file

@ -0,0 +1,239 @@
# Git push.
function gps() {
git push "${@}"
}
# Git push all (branches). Useful for pushing all stuff to a new remote.
function gpsa() {
local remotes=($(git remote))
for remote in ${remotes[@]}; do
echo -n "${remote}: "
git push "${remote}" --tags "refs/remotes/origin/*:refs/heads/*"
done
}
# Git force push.
function gpsf() {
git push --force "${@}"
}
# Git pull.
function gpl() {
git pull "${@}"
}
# Git log.
function gl() {
git log "${@}"
}
# Git status.
function gs() {
git status "${@}"
}
# Git stash.
function gst() {
git stash "${@}"
}
# Git diff.
function gd() {
git diff "${@}"
}
# Git commit.
function gc() {
git commit -m "${@}"
}
# Git checkout.
function gch() {
git checkout "${@}"
}
# Git checkout branch.
# Usage: gchb <BRANCH>
function gchb() {
git checkout -b "${@}"
}
# Git branch.
function gb() {
git branch --all "${@}"
}
# Git branch delete.
# Usage: gbd <BRANCH>
function gbd() {
git branch -D "${@}"
}
# Git branch delete all except current.
function gbda() {
git branch | grep -v ^* | xargs git branch -D
}
# Git fetch all.
function gf() {
git fetch --all -v -p
}
# Git tag.
function gt() {
git tag "${@}"
}
# Git ignore files.
function gi() {
git ls-files -ci --exclude-standard -z | xargs -0 git rm --cached
}
# Git patch create.
# Usage: gpc <FILE>
function gpc() {
git diff > "${@}"
}
# Git patch (apply).
# Usage: gp <FILE>
function gp() {
git apply "${@}"
}
# Run git garbage collection.
function ggc() {
git gc --aggressive --no-cruft --prune=now
}
# Preview diff while adding. Adds current dir by default.
# Usage: ga [FILES]
function ga() {
local target=${@}
if [[ "${target}" = "" ]]; then
target="."
fi
git diff ${target}
git add ${target}
}
# Rebase by X commits or from root. When COUNT is 0 - rebase from root. Default is 2.
# Usage: gr [COMMIT COUNT]
function gr() {
local base="${1}"
# rebase last 2 commits by default.
if [[ "${base}" = "" ]]; then
base="2"
fi
# if 0, rebase from root. else from specified base.
if [[ "${base}" = "0" ]]; then
git rebase -i --root
else
git rebase -i HEAD~${base}
fi
}
# Specify git user as Dmitry Voronin with provided email.
# Usage: gu [EMAIL]
function gu() {
local name="Dmitry Voronin"
local email="${1}"
if [[ "${name}" = "" || "${email}" = "" ]]; then
echo "usage: gu [EMAIL]"
return 2
fi
git config user.name "${name}"
git config user.email "${email}"
}
# Get my git repo.
# Usage: gg <REPO>
function gg() {
local repo="${1}"
if [[ "${repo}" = "" ]]; then
help gg
return 2
fi
git clone https://git.voronind.com/voronind/"${repo}"
}
# See diff for a specific commit. Last commit by default.
# Usage: gdc [COMMITHASH]
function gdc() {
local hash="${1}"
[[ "${hash}" = "" ]] && hash="HEAD"
git diff "${hash}^!"
}
# Get version number based on commit count.
function gv() {
git rev-list HEAD --count
}
# Show current branch.
function _git_current_branch() {
git branch --show-current 2> /dev/null
}
# Show origin's url.
function _git_origin_url() {
git remote get-url origin
}
# Get this dotfiles url.
function _git_dotfiles_url() {
echo 'https://git.voronind.com/voronind/linux.git'
}
# Check if current git repo is this dotfiles.
function _git_is_dotfiles() {
# [[ "$(_git_origin_url)" = "$(_git_dotfiles_url)" ]]
local dir="${PWD}"
while [[ "${dir}" != "" ]]; do
if [[ -d "${dir}/.git" ]]; then
if [[ "${dir}" = "${HOME}" ]] || [[ "${dir}" = "$(realpath ${HOME})" ]]; then
return 0
else
return 1
fi
fi
dir="${dir%/*}"
done
}
# autocomplete.
_completion_loader git &> /dev/null
__git_complete gps _git_push &> /dev/null
__git_complete gpsf _git_push &> /dev/null
__git_complete gpl _git_pull &> /dev/null
__git_complete gl _git_log &> /dev/null
__git_complete gs _git_status &> /dev/null
__git_complete gst _git_stash &> /dev/null
__git_complete gd _git_diff &> /dev/null
__git_complete gdc _git_diff &> /dev/null
__git_complete gc _git_commit &> /dev/null
__git_complete gch _git_checkout &> /dev/null
__git_complete gchb _git_checkout &> /dev/null
__git_complete gb _git_branch &> /dev/null
__git_complete gbd _git_branch &> /dev/null
__git_complete gf _git_fetch &> /dev/null
__git_complete gt _git_tag &> /dev/null
__git_complete gp _git_apply &> /dev/null
__git_complete ga _git_add &> /dev/null
# Autocomplete with my git emails.
function _gu() {
_autocomplete_first account@voronind.com dd.voronin@fsight.ru
}
complete -F _gu gu

View file

@ -0,0 +1,69 @@
# Group files by extension.
# Usage: group_ext [FILES]
function group_ext() {
local IFS=$'\n'
local targets=(${@})
[[ "${targets}" = "" ]] && targets=($(_ls_file))
process() {
local ext=${target##*.}
[[ -d "${target}" ]] && { _iterate_skip "Is a directory."; return 0; }
[[ "${ext}" = "${target}" ]] && { _iterate_skip "No extension."; return 0; }
mkdir ${ext} 2> /dev/null
mv -- ${target} ./${ext}/${target}
}
_iterate_targets process ${targets[@]}
}
# Group files and dirs by year.
# Usage: group_year [FILES]
function group_year() {
local IFS=$'\n'
local targets=(${@})
[[ "${targets}" = "" ]] && targets=($(ls))
process() {
local year=$(stat --format=%y ${target})
year=${year%%-*}
mkdir ${year} 2> /dev/null
mv -- ${target} ./${year}/${target}
}
_iterate_targets process ${targets[@]}
}
# Copy files from current year to the named dir.
# Usage: group_year_copy <YEAR> [FILES]
function group_year_copy() {
local IFS=$'\n'
local selected_year="${1}"
local targets=(${@:2})
if [[ "${selected_year}" = "" ]]; then
help group_year_copy
return 2
fi
# All files by default.
[[ "${targets}" = "" ]] && targets=($(ls))
mkdir ${selected_year} 2> /dev/null
process() {
local year=$(stat --format=%y ${target})
year=${year%%-*}
if [[ "${year}" = "${selected_year}" ]]; then
rcp -- ${target} ./${selected_year}/
else
_iterate_skip
fi
}
_iterate_targets process ${targets[@]}
}

View file

@ -0,0 +1,25 @@
# Get help about dotfiles bash function.
# Usage: help <FUNCTION>
function help() {
local fun="${1}"
if [[ "${fun}" = "" ]] || [[ "$(find_function | grep ${fun})" = "" ]]; then
help help
return 2
fi
sed -e '$s/$/\n/' -s "${BASH_MODULE_PATH}"/* | sed -n -e "/function ${fun}()/q;p" | tac | sed -n -e "/^$/q;p" | tac | sed -e "s/^# \+//" -e "\$i \ "
}
# Short for help.
# Usage: h <FUNCTION>
function h() {
help "${@}"
}
# Autocomplete with available functions.
function _help_functions() {
_autocomplete_first $(find_function)
}
complete -F _help_functions help h

View file

@ -0,0 +1,64 @@
# Unset possible system-defined aliases.
unalias l ll lll llll la lla &> /dev/null
unset l ll lll llll la lla &> /dev/null
# List files in dirs.
# Current dir by default.
# Usage: l [DIRS]
function l() {
ls -lhv --si --group-directories-first --color=auto -- "$@"
}
# List last modified files first.
# Current dir by default.
# Usage: ll [DIRS]
function ll() {
ls -lhvtr --si --color=auto -- "$@"
}
# List files in tree structure.
# Current dir by default.
# Depth can be omitted by passing `-` (dash).
# Usage: lll [DEPTH] [DIRS]
function lll() {
local IFS=$'\n'
local depth="${1}"
local target=("${@:2}")
[[ "${target}" = "" ]] && target="."
[[ "${depth}" = "" ]] && depth=666
[[ "${depth}" = "-" ]] && depth=666
tree -a -L "${depth}" -- "${target[@]}"
}
# List files recursively.
# Current dir by default.
# Usage: llll [DIRS]
function llll() {
ls -RlAhv --si --group-directories-first --color=auto -- "$@"
}
# List all files in dirs, incl. hidden files.
# Current dir by default.
# Usage: la [DIRS]
function la() {
ls -lAh --si --group-directories-first --color=auto -- "$@"
}
# List all files in dirs, incl. hidden files, sorted by mtime.
# Current dir by default.
# Usage: lla [DIRS]
function lla() {
ls -lAhtr --si --color=auto -- "$@"
}
# List only files.
function _ls_file() {
ls --classify | grep -v \/$
}
# List only dirs.
function _ls_dir() {
ls --classify | grep \/$ | sed -e "s/\/$//"
}

View file

@ -0,0 +1,15 @@
# Render markdown in browser using Gitea API. Because I want consistency with Gitea web render.
# Works only inside LAN.
# Usage: markdown_render <FILE.md>
function markdown_render() {
local IFS=$'\n'
local file="${1}"
local render="markdown_render.html"
if [[ "${file}" = "" ]]; then
help markdown_render
return 2
fi
curl -X POST https://git.voronind.com/markdown -d "$(cat ${file})" > "${render}" && o "${render}" && sleep 2 && rm "${render}"
}

View file

@ -0,0 +1,395 @@
# Rename dirs to `snake_case` and files to `PascalCase`. Careful with structured file names like archives!
# Usage: name [FILES]
function name() {
local IFS=$'\n'
local targets=(${@})
[[ "${targets}" = "" ]] && targets=($(ls))
process() {
# Skip archive.
if $(_is_archive ${target}); then
_iterate_skip "File is an archive, skip."
return 0
fi
if [[ -d "${target}" ]]; then
local new_name=$(parse_snake ${target})
[[ -e "${new_name}" ]] && return 0
mv -- ${target} ${new_name} && echo ${new_name}
else
local ext=".${target##*.}"
local name=${target%.*}
[[ "${ext}" = ".${target}" ]] && ext=""
local new_name="$(parse_pascal ${name})${ext}"
[[ -e "${new_name}" ]] && return 0
mv -- ${target} ${new_name} && echo ${new_name}
fi
}
_iterate_targets process ${targets[@]}
}
# Rename files with provided parser, i.e. `parse_simple`.
# All files by default.
# Usage: name_parse <PARSER> [FILES]
function name_parse() {
local IFS=$'\n'
local parser=${1}
local targets=(${@:2})
[[ "${targets}" = "" ]] && targets=([^.]*)
if [[ "${parser}" = "" ]]; then
help name_parse
return 2
fi
process() {
# Skip archive.
if $(_is_archive ${target}); then
_iterate_skip "File is an archive, skip."
return 0
fi
# parse new name.
local ext=""
local name="${target}"
# ext only for files.
if [[ -f "${target}" ]]; then
ext=".${target##*.}"
name="${target%.*}"
fi
# Files w/o extension support.
[[ "${ext#.}" = "${name}" ]] && ext=""
# Get new name.
local new_name=$(${parser} "${name}")${ext,,}
# check if same name.
[[ "${target}" = "${new_name}" ]] && return 0
# check if target name already exists.
if [[ -f "${new_name}" ]]; then
_error "${new_name}: Already exists!"
return 1
fi
# rename target.
mv -- "${target}" "${new_name}" && echo "${new_name}"
}
_iterate_targets process ${targets[@]}
}
# Rename all files to their hashes while keeping extensions.
# All files by default.
# Usage: name_hash [FILES]
function name_hash() {
local IFS=$'\n'
local targets=(${@})
[[ "${targets}" = "" ]] && targets=($(_ls_file))
process() {
# extract extension.
local extension="${target##*.}"
if [[ "${extension}" = "${target}" ]]; then
extension=""
else
extension=".${extension}"
fi
# hash the new name.
local hash=$(pv "${target}" | sha1sum | cut -d\ -f1)
new_name="${hash,,}${extension,,}"
# check if same name.
[[ "${target}" = "${new_name}" ]] && return 0
# rename target.
mv -- ${target} ${new_name} && echo ${new_name}
}
_iterate_targets process ${targets[@]}
}
# Check hashes for previously renamed files.
# All files by default.
# Usage: name_hash_check [FILES]
function name_hash_check() {
local IFS=$'\n'
local targets=(${@})
[[ "${targets}" = "" ]] && targets=([^.]*)
process() {
# extract hashes.
local stored="${target%%.*}"
local actual=$(pv "${target}" | sha1sum | cut -d\ -f1)
# compare hashes.
if [[ "${stored}" != "${actual}" ]]; then
_error "Failed."
return 1
fi
}
_iterate_targets process ${targets[@]}
}
# Rename files for Jellyfin shows, i.e. `Episode S01E01.mkv`
# All files by default.
# Usage: name_show [FILES]
function name_show() {
local IFS=$'\n'
local season="$(realpath .)"; season="${season##*\ }"
local episode=0
local targets=(${@})
[[ "${targets}" = "" ]] && targets=($(_ls_file))
# Error when no season number specified.
if [[ "${season}" = "" ]]; then
_error "Could not determine season number."
return 2
fi
process() {
((episode++))
# extract new name.
local new_name="Episode S${season}E$(printf %02d ${episode}).${target##*.}"
# Skip on no change.
[[ "${target}" = "${new_name}" ]] && return 0
# rename target.
mv -- ${target} ${new_name} && echo ${new_name}
}
_iterate_targets process ${targets[@]}
}
# Rename files for Kavita manga format.
# All files by default.
# Usage: name_manga <SEASON> [FILES]
function name_manga() {
local IFS=$'\n'
local manga=${PWD##*/}
local season=${1}
local episode=0
local targets=(${@:2})
[[ "${targets}" = "" ]] && targets=($(_ls_file))
# Error when no season number specified.
if [[ "${season}" = "" ]]; then
help name_manga
return 2
fi
process() {
((episode++))
# Extract new name.
local new_name="${manga} Vol.${season} Ch.${episode}.${target##*.}"
# Skip on no change.
[[ "${target}" = "${new_name}" ]] && return 0
# Rename target.
mv -- ${target} ${new_name} && echo ${new_name}
}
_iterate_targets process ${targets[@]}
}
# Rename files for ffmpeg_music_meta format.
# All files by default.
# Usage: name_music [FILES]
function name_music() {
local IFS=$'\n'
local targets=(${@})
[[ "${targets}" = "" ]] && targets=($(ls))
process() {
# Extract new name.
local ext=${target##*.}
if [[ -d "${target}" ]]; then
local new_name="$(parse_titlecase $(parse_simple ${target%.*}))"
else
local new_name="$(parse_titlecase $(parse_simple ${target%.*})).${ext}"
fi
# Skip on no change.
[[ "${target%/}" = "${new_name}" ]] && return 0
# Rename target.
mv -- ${target} ${new_name} && echo ${new_name}
}
_iterate_targets process ${targets[@]}
}
# Rename files with new extension.
# All files by default.
# Usage: name_ext <EXTENSION> [FILES]
function name_ext() {
local IFS=$'\n'
local extension=${1}
local targets=(${@:2})
[[ "${targets}" = "" ]] && targets=($(_ls_file))
# Error when no new extension specified.
if [[ "${extension}" = "" ]]; then
help name_ext
return 2
fi
process() {
# Extract new name.
local new_name="${target%.*}"."${extension}"
# Skip on no change.
[[ "${target}" = "${new_name}" ]] && return 0
# Rename target.
mv -- ${target} ${new_name} && echo ${new_name}
}
_iterate_targets process ${targets[@]}
}
# Change file name prefix.
# All matching files by default.
# Usage: name_prefix <OLD> <NEW> [FILES]
function name_prefix() {
local IFS=$'\n'
local old=${1}
local new=${2}
local targets=(${@:3})
[[ "${targets}" = "" ]] && targets=(${old}*)
process() {
# Create new name.
local new_name="${new}${target#$old}"
# Skip on no change.
[[ "${target}" = "${new_name}" ]] && return 0
# Rename.
mv -- ${target} ${new_name} && echo ${new_name}
}
_iterate_targets process ${targets[@]}
}
# Change file name postfix.
# All matching files by default.
# Usage: name_postfix <OLD> <NEW> [FILES]
function name_postfix() {
local IFS=$'\n'
local old=${1}
local new=${2}
local targets=(${@:3})
[[ "${targets}" = "" ]] && targets=(*${old})
process() {
# Create new name.
local new_name="${target%$old}${new}"
# Skip on no change.
[[ "${target}" = "${new_name}" ]] && return 0
# Rename.
mv -- ${target} ${new_name} && echo ${new_name}
}
_iterate_targets process ${targets[@]}
}
# Replace part of the name.
# All matching files by default.
# Usage: name_replace <OLD> <NEW> [FILES]
function name_replace() {
local IFS=$'\n'
local old=${1}
local new=${2}
local targets=(${@:3})
[[ "${targets}" = "" ]] && targets=(*${old}*)
process() {
# Create new name.
local new_name="${target//$old/$new}"
# Skip on no change.
[[ "${target}" = "${new_name}" ]] && return 0
# Rename.
mv -- ${target} ${new_name} && echo ${new_name}
}
_iterate_targets process ${targets[@]}
}
# Fix numbering for numbered files. I.e if there are 10 items and some of them start without zero, then append zero to it. 1..10 -> 01..10.
# Usage: name_fix_numbering [FILES]
function name_fix_numbering() {
local IFS=$'\n'
local highest=0
local power=0
local targets=(${@})
[[ "${targets}" = "" ]] && targets=($(ls | grep "^[0-9]"))
# Count leading zeroes.
for target in "${targets[@]}"; do
# Check that starts with a digit.
[[ "${target}" =~ ^[0-9] ]] || continue
local digits=($(parse_ints "${target}"))
local digit="${digits[0]}"
digit=$((10#${digit}))
[[ "${digit}" -gt "${highest}" ]] && highest="${digit}"
done
local i=${highest}
while [[ i -gt 0 ]]; do
((power++))
i=$((${i}/10))
done
process() {
# Check that starts with a digit.
if [[ ! "${target}" =~ ^[0-9] ]]; then
_error "Does not start with a digit!"
return 1
fi
# Prepare new name.
local digits=($(parse_ints "${target}"))
local digit="${digits[0]}"
digit=$((10#${digit}))
local new_name=$(printf "%0${power}d" "${digit}")"${target#${digits[0]}}"
# Skip if the same name.
[[ "${target}" = "${new_name}" ]] && return 0
# Check that file does not exist.
if [[ -e "${new_name}" ]]; then
_error "${new_name}: File exists!"
return 1
fi
mv -- ${target} ${new_name} && echo ${new_name}
}
_iterate_targets process ${targets[@]}
}
function _comp_name_parse() {
_autocomplete_first_ls $(find_function | grep ^parse)
}
complete -o filenames -F _comp_name_parse name_parse

View file

@ -0,0 +1,82 @@
export _nix_system_config="git+https://git.voronind.com/voronind/nixos.git"
# Rebuild system.
# Optionally force the hostname.
# Usage: nix_rebuild [HOSTNAME]
function nix_rebuild() {
local target="${1}"
[[ "${target}" = "" ]] && target="${HOSTNAME}"
nixos-rebuild boot --flake "${_nix_system_config}#${target}"
}
# Rebuild and switch system.
# Optionally force the hostname.
# Usage: nix_switch [HOSTNAME]
function nix_switch() {
local target="${1}"
[[ "${target}" = "" ]] && target="${HOSTNAME}"
nixos-rebuild switch --flake "${_nix_system_config}#${target}"
}
# Update system versions.
# Usage: nix_update
function nix_update() {
nix flake update "${_nix_system_config}"
}
# Spawn shell with specified nix environment.
# Uses flake.nix in current dir by default.
# Usage: nix_shell [NAME]
function nix_shell() {
local target="${1}"
[[ "${target}" = "" ]] && target="default"
nix build ".#devShells.${NIX_CURRENT_SYSTEM}.${target}" -o ".NixRoot${target^}"
NIX_SHELL="${target}" nix develop ".#devShells.${NIX_CURRENT_SYSTEM}.${target}"
}
alias shell="nix_shell"
# Spawn nix-shell with specified packages.
# Usage: nix_tmpshell <PACKAGES>
function nix_tmpshell() {
local IFS=$'\n'
local input=("${@}")
local pkgs=()
local tag="${NIX_SHELL}"
if [[ "${input}" = "" ]]; then
help nix_tmpshell
return 2
fi
[[ "${tag}" = "" ]] && tag="${1}"
for pkg in ${input[@]}; do
pkgs+=("nixpkgs#${pkg}")
done
NIX_SHELL="${tag}" NIXPKGS_ALLOW_UNFREE=1 nix shell --impure ${pkgs[@]}
}
alias tmpshell="nix_tmpshell"
# Build live image.
function nix_live() {
nix build "${_nix_system_config}#nixosConfigurations.live.config.system.build.isoImage"
}
# Switch nix-on-droid.
function nixdroid_switch() {
nix-on-droid switch --flake .config/linux/system
}
# Autocomplete with available hosts.
function _comp_hosts() {
local IFS=$'\n'
local targets=($(ls ~/.config/linux/system/host/))
_autocomplete_first ${targets[@]}
}
complete -F _comp_hosts nix_switch nix_rebuild

View file

@ -0,0 +1,11 @@
# Send Telegram notification.
# Usage: notify <MESSAGE>
function notify() {
curl -X POST -H 'Content-Type: Application/json' -d "{\"chat_id\":\"155897358\",\"text\":\"$1\"}" https://api.telegram.org/bot2046849441:AAHQpjRK4xpL8tEUyN4JTSDUUze4J0wSIy4/sendMessage &> /dev/null
}
# Send silent Telegram notification.
# Usage: notify_silent <MESSAGE>
function notify_silent() {
curl -X POST -H 'Content-Type: Application/json' -d "{\"chat_id\":\"155897358\",\"text\":\"$1\",\"disable_notification\":\"true\"}" https://api.telegram.org/bot2046849441:AAHQpjRK4xpL8tEUyN4JTSDUUze4J0wSIy4/sendMessage &> /dev/null
}

View file

@ -0,0 +1,30 @@
# Change file ownership to specified user id and restrict access to him.
# Root user by default. This directory recursively by default.
# Usage: own [USER] [FILES]
function own() {
local IFS=$'\n'
local files=("${@:2}")
local user="${1}"
local group="${1}"
# default to current dir.
if [ "${files[*]}" = "" ]; then
files=(".")
fi
# default to current user.
if [ "${user}" = "" ]; then
user="${UID}"
fi
# If not root, default to users group.
[[ "${user}" = 0 ]] && group="0" || group="100"
for file in "${files[@]}"; do
# set ownership.
chown "${user}":"${group}" -R "${file}" &> /dev/null
# remove access from group and others.
chmod -077 -R "${file}"
done
}

View file

@ -0,0 +1,187 @@
export _unpack_supported=".tar$|.tgz$|.txz$|.tar.gz$|.tar.xz$|.zip$|.iso$|.rar$"
# Pack files into desired format.
# All files and directories by default.
# Usage: pack <TARGET.ext> [FILES]
function pack() {
local IFS=$'\n'
local output="${1}"
local targets=("${@:2}")
local format="${output##*.}"
local name="${output%.*}"
# report no output.
if [[ "${output}" = "" ]]; then
help pack
return 2
fi
# report no format.
if [[ "${format}" = "" ]]; then
_error "Could not determine output format."
help pack
return 2
fi
# All targets by default.
[[ "${targets}" = "" ]] && targets=(*)
case "${format}" in
"tgz")
_pack_tgz "${output}" "${targets[@]}"
;;
"txz")
_pack_txz "${output}" "${targets[@]}"
;;
"tar")
_pack_tar "${output}" "${targets[@]}"
;;
"zip")
_pack_zip "${output}" "${targets[@]}"
;;
"gz")
_pack_gz "${output}" "${targets[@]}"
;;
"xz")
_pack_xz "${output}" "${targets[@]}"
;;
"iso")
_pack_iso "${output}" "${targets[@]}"
;;
*)
_error "${target}: Format not supported."
return 2
;;
esac
}
# Attempt to unpack.
# All supported formats by default.
# Usage: unpack [FILES]
function unpack() {
local IFS=$'\n'
local targets=(${@})
[[ "${targets}" = "" ]] && targets=($(_ls_files | grep -E ${_unpack_supported}))
process() {
# unpack file type.
local type="${target##*.}"
[[ "${target}" =~ .tar.gz$ ]] && type="tar.gz"
[[ "${target}" =~ .tar.xz$ ]] && type="tar.xz"
# unpack content.
case "${type,,}" in
"zip")
_unpack_zip "${target}"
;;
"7z")
_unpack_7z "${target}"
;;
"tgz"|"tar.gz")
_unpack_tgz "${target}"
;;
"txz"|"tar.xz")
_unpack_txz "${target}"
;;
"tar")
_unpack_tar "${target}"
;;
"iso")
_unpack_iso "${target}"
;;
"rar")
_unpack_rar "${target}"
;;
"xz")
_unpack_xz "${target}"
;;
"gz")
_unpack_gz "${target}"
;;
*)
_error "${target}: Format not supported."
return 2
;;
esac
}
_iterate_targets process ${targets[@]}
}
function _pack_zip() {
zip -9 -r "${@}"
}
function _pack_tgz() {
tar -c "${@:2}" | pv -s $(/usr/bin/env du -csb "${@:2}" | sed -n -e '$p' | awk '{print $1}') | gzip -1 > "${1}"
}
function _pack_txz() {
tar -c "${@:2}" | pv -s $(/usr/bin/env du -csb "${@:2}" | sed -n -e '$p' | awk '{print $1}') | xz -9e > "${1}"
}
function _pack_tar() {
tar -c "${@:2}" | pv -s $(/usr/bin/env du -csb "${@:2}" | sed -n -e '$p' | awk '{print $1}') > "${1}"
}
function _pack_gz() {
pv "${2}" | gzip -1 > "${1}"
}
function _pack_xz() {
pv "${2}" | xz -9e > "${1}"
}
function _pack_iso() {
local input=("${@:2}")
local output="${1}"
local args=()
for arg in ${input[@]}; do
[[ -d "${arg}" ]] || {
_error "${arg} is not a directory."
return 1
};
args+=("${arg}=${arg}")
done
genisoimage -J -r -pad -o "${output}" -graft-points "${args[@]}"
}
function _unpack_zip() {
unzip "${1}"
}
function _unpack_7z() {
7za x "${1}"
}
function _unpack_tgz() {
pv "${1}" | gzip -d | tar -xf -
}
function _unpack_txz() {
pv "${1}" | xz -d | tar -xf -
}
function _unpack_tar() {
pv "${1}" | tar -xf -
}
function _unpack_iso() {
7za x "${1}"
}
function _unpack_rar() {
unrar x "${1}"
}
function _unpack_gz() {
pv "${1}" | gzip -d > "${1%.gz}"
}
function _unpack_xz() {
pv "${1}" | xz -d > "${1%.xz}"
}

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