Compare commits

..

No commits in common. "master" and "eww" have entirely different histories.
master ... eww

660 changed files with 4500 additions and 64024 deletions

View file

@ -1,19 +0,0 @@
name: Discord
on:
- workflow_dispatch
- push
jobs:
discord_commits:
runs-on: ubuntu-latest
name: discord commits
if: contains(github.event.head_commit.message, '(servers)')
steps:
- name: Discommit
uses: https://github.com/matt1432/discommit@v0.0.2
with:
discord_webhook: ${{ secrets.DISCORD_WEBHOOK }}
api_url: 'https://git.nelim.org/api/v1/repos/$OWNER/$REPO/git/commits/$REF'
title: 'New commit containing changes to server configs:'

5
.gitattributes vendored
View file

@ -1,5 +0,0 @@
flake.lock -diff
flake.nix -diff
**/non-declarative-conf -diff
**/package-lock.json -diff
**/HomeAssistantGenerated -diff

22
.gitignore vendored
View file

@ -1,23 +1 @@
# Python
*.egg-info
# NPM
*node_modules
*build/
# Direnv
*.direnv/
# Generated by nix
result*
!results/
.nixd.json
## AGS
**/vars.ts
**/config.js
*icons
**/types
# Other
*.temp

View file

@ -1,16 +0,0 @@
MIT No Attribution
Copyright 2024 Mathis H.
Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

107
README.md
View file

@ -1,100 +1,13 @@
# My NixOS configs
what is currently not working:
- plymouth theme has no login prompt
- sddm theme flashes white
- fixme: swaync acts up with eww
- autosign in to keyring
## AGS
what i want to do:
- learn flakes
- add auto-rotate widget in eww control center
You might find it weird that most of my config is written in TypeScript.
That's because all my desktops run
[AGS](https://github.com/Aylur/ags)
for UI. Click on
[this](https://git.nelim.org/matt1432/nixos-configs/src/branch/master/modules/ags)
to see my configuration.
# Docs
I'm also a victim of Stockholm syndrome at this point and make my scripts
in TypeScript because it's the scripting language I am most comfortable with.
## About
### General
This repo is the complete configuration of machines I own running NixOS or Nix
and any other related smaller projects exposed by a Nix Flake.
Its main directory structure is based on a flake's
[outputs](https://wiki.nixos.org/wiki/Flakes#Output_schema).
I try to follow a few rules to better organise my Nix code:
- Every main subdirectory only has an optional `default.nix` and subfolders for each
of its attributes.
- Inside a subdirectory, if there is non nix code, it will be in a `config` folder.
- Every module should not do anything if imported. An enable option should be toggled
for it to have any effect.
- Any nix file that represents a module should be named `default.nix` (a nix file
which is imported directly can be called anything else alongside `default.nix`)
### Flake Location
This git repo will always be located at `$FLAKE` (`config.environment.variables.FLAKE`)
and symlinked to `/etc/nixos` to have everything where NixOS tools
expect things to be.
ie.
```bash
sudo rm -r /etc/nixos
echo "$FLAKE" # /home/matt/.nix
sudo ln -sf /home/matt/.nix /etc/nixos
```
### Subdirectories
| Output / Directory | Description |
| -------------------- | ----------- |
| `apps` | [Misc scripts ran from the flake](./apps) |
| `configurations` | [device, ISO and nix-on-droid configurations](./configurations) |
| `devShells` | [Development shells for a bunch of projects and languages](./devShells) |
| `homeManagerModules` | [Modules made for home-manager](./homeManagerModules) |
| `inputs` | [Pre-evaluated flake inputs](./inputs) |
| `lib` | [Custom Nix functions made easily available](./lib) |
| `modules` | [Modules made for NixOS systems](./modules) |
| `nixFastChecks` | [Attribute set of derivations exposed by this flake](./nixFastChecks) |
| `overlays` | [Nixpkgs overlays](./overlays) |
| `packages` | [Some custom packages not available in nixpkgs or modified from it](./packages) |
| `results` | Directory where I neatly keep my result symlinks from `nixFastChecks` |
| `scopedPackages` | [Some custom package scopes not available in nixpkgs or modified from it](./scopedPackages) |
### Secrets
All my secrets are in a private git repo that makes use of
[sops-nix](https://github.com/Mic92/sops-nix).
I generate `.sops.yaml` from `.sops.nix`:
```nix
let
wim = "somekey";
binto = "somekey2";
in {
creation_rules = [
{
path_regex = "secrets/[^/]+\\.(yaml|json|env|ini)$";
key_groups = [
{
age = [wim binto];
}
];
}
];
}
```
which is then converted to `.sops.yaml` using
[remarshal](https://github.com/remarshal-project/remarshal)
and this shell command:
```bash
nix eval --json --file ./.sops.nix | remarshal --if json --of yaml > .sops.yaml
```
TLDR: I **[hate](https://ruudvanasseldonk.com/2023/01/11/the-yaml-document-from-hell)** YAML
Since I use my laptop with one user, I symlinked the configs to my home directory following the tutorial [here](https://nixos.wiki/wiki/NixOS_configuration_editors)

View file

@ -1,116 +0,0 @@
{
inputs = import ./inputs;
outputs = inputs @ {
self,
systems,
nixpkgs,
secrets,
...
}: let
inherit (self.lib) mkVersion mkNixOS mkNixOnDroid mkPkgs;
perSystem = attrs:
nixpkgs.lib.genAttrs (import systems) (system:
attrs (mkPkgs {inherit system nixpkgs;}));
in {
lib = import ./lib {inherit inputs perSystem;};
nixOnDroidConfigurations.default =
mkNixOnDroid [./configurations/android];
nixosConfigurations = {
# Desktops
wim = mkNixOS {
extraModules = [
./configurations/wim
secrets.nixosModules.default
];
};
binto = mkNixOS {
cudaSupport = true;
extraModules = [./configurations/binto];
};
bbsteamie = mkNixOS {
mainUser = "mariah";
extraModules = [./configurations/bbsteamie];
};
# NAS
nos = mkNixOS {
cudaSupport = true;
extraModules = [
./configurations/nos
secrets.nixosModules.nos
];
};
# Build / test server
servivi = mkNixOS {
extraModules = [
./configurations/servivi
secrets.nixosModules.servivi
];
};
# Home-assistant
homie = mkNixOS {
extraModules = [
./configurations/homie
secrets.nixosModules.homie
];
};
# Cluster
thingone = mkNixOS {
extraModules = [
(import ./configurations/cluster "thingone")
secrets.nixosModules.thingy
];
};
thingtwo = mkNixOS {
extraModules = [
(import ./configurations/cluster "thingtwo")
secrets.nixosModules.thingy
];
};
live-image = mkNixOS {
mainUser = "nixos";
extraModules = [./configurations/live-image];
};
};
# For nix-fast-build. I use a custom output to alleviate eval time of this flake. ie. when doing nix flake show
nixFastChecks = import ./nixFastChecks {inherit perSystem self;};
homeManagerModules = import ./homeManagerModules {inherit self;};
nixosModules = import ./modules {inherit self;};
overlays = import ./overlays {inherit self;};
apps =
perSystem (pkgs:
import ./apps {inherit pkgs self;});
appsPackages =
perSystem (pkgs:
import ./apps/packages.nix {inherit inputs pkgs;});
devShells =
perSystem (pkgs:
import ./devShells {inherit pkgs self;});
packages =
perSystem (pkgs:
import ./packages {inherit inputs mkVersion pkgs;});
scopedPackages =
perSystem (pkgs:
import ./scopedPackages {inherit inputs mkVersion pkgs;});
formatter = perSystem (pkgs: pkgs.alejandra);
};
}

View file

@ -1,12 +0,0 @@
# Apps
This directory contains every derivations for apps exposed by this flake.
## List of my apps found in `self.apps`
| Name | Description |
| ---- | ----------- |
| `extract-subs` | Extract all `srt` subtitle files from a `mkv` video with the appropriate name. |
| `gen-docs` | Generates the READMEs in this repository from nix attributes. |
| `pin-inputs` | Takes a list of inputs to pin to their current rev in `flake.lock`. |
| `update-sources` | Updates all derivation sources in this repository and generates a commit message for the changes made. |

View file

@ -1,40 +0,0 @@
{
lib,
src,
npmDepsHash,
runtimeInputs,
buildNpmPackage,
meta,
makeWrapper,
nodejs_latest,
jq,
...
}: let
inherit (lib) concatMapStringsSep;
inherit (builtins) fromJSON readFile;
packageJSON = fromJSON (readFile "${src}/package.json");
pname = packageJSON.name;
inherit (packageJSON) version;
in
buildNpmPackage {
inherit pname version src runtimeInputs npmDepsHash;
prePatch = ''
mv ./tsconfig.json ./project.json
sed 's/^ *\/\/.*//' ${./config/tsconfig.json} > ./base.json
${jq}/bin/jq -sr '.[0] * .[1] | del(.extends)' ./project.json ./base.json > ./tsconfig.json
rm base.json project.json
'';
nativeBuildInputs = [makeWrapper];
postInstall = ''
wrapProgram $out/bin/${pname} \
--prefix PATH : ${concatMapStringsSep ":" (p: p + "/bin") runtimeInputs}
'';
nodejs = nodejs_latest;
meta = {mainProgram = pname;} // meta;
}

View file

@ -1,2 +0,0 @@
use flake $FLAKE#node
npm ci

View file

@ -1,451 +0,0 @@
import eslint from '@eslint/js';
import jsdoc from 'eslint-plugin-jsdoc';
import stylistic from '@stylistic/eslint-plugin';
import tseslint from 'typescript-eslint';
export default tseslint.config({
files: ['**/*.js', '**/*.ts'],
ignores: ['node_modules/**', 'types/**'],
extends: [
eslint.configs.recommended,
jsdoc.configs['flat/recommended-typescript'],
stylistic.configs['recommended-flat'],
...tseslint.configs.recommended,
...tseslint.configs.stylistic,
],
rules: {
// JSDoc settings
'jsdoc/tag-lines': ['warn', 'any', { startLines: 1 }],
'jsdoc/check-line-alignment': ['warn', 'always', {
tags: ['param', 'arg', 'argument', 'property', 'prop'],
}],
'jsdoc/no-types': 'off',
// Newer settings
'@typescript-eslint/no-extraneous-class': ['off'],
'@typescript-eslint/no-implied-eval': ['off'],
'class-methods-use-this': 'off',
'@stylistic/no-multiple-empty-lines': 'off',
// Pre-flat config
'@typescript-eslint/no-unused-vars': [
'error',
{
args: 'all',
argsIgnorePattern: '^_',
caughtErrors: 'all',
caughtErrorsIgnorePattern: '^_',
destructuredArrayIgnorePattern: '^_',
varsIgnorePattern: '^_',
ignoreRestSiblings: true,
},
],
'array-callback-return': [
'error',
{
allowImplicit: true,
checkForEach: true,
},
],
'no-constructor-return': [
'error',
],
'no-unreachable-loop': [
'error',
{
ignore: [
'ForInStatement',
'ForOfStatement',
],
},
],
'no-use-before-define': [
'error',
{
functions: false,
},
],
'block-scoped-var': [
'error',
],
'curly': [
'warn',
],
'default-case-last': [
'warn',
],
'default-param-last': [
'error',
],
'eqeqeq': [
'error',
'smart',
],
'func-names': [
'warn',
'never',
],
'func-style': [
'warn',
'expression',
],
'logical-assignment-operators': [
'warn',
'always',
],
'no-array-constructor': [
'error',
],
'no-empty-function': [
'warn',
],
'no-empty-static-block': [
'warn',
],
'no-extend-native': [
'error',
],
'no-extra-bind': [
'warn',
],
'no-implicit-coercion': [
'warn',
],
'no-iterator': [
'error',
],
'no-labels': [
'error',
],
'no-lone-blocks': [
'error',
],
'no-lonely-if': [
'error',
],
'no-loop-func': [
'error',
],
'no-magic-numbers': [
'error',
{
ignore: [
-1,
0.1,
0,
1,
2,
3,
4,
5,
10,
12,
33,
66,
100,
255,
360,
450,
500,
1000,
],
ignoreDefaultValues: true,
ignoreClassFieldInitialValues: true,
},
],
'no-multi-assign': [
'error',
],
'no-new-wrappers': [
'error',
],
'no-object-constructor': [
'error',
],
'no-proto': [
'error',
],
'no-return-assign': [
'error',
],
'no-sequences': [
'error',
],
'no-shadow': [
'error',
{
builtinGlobals: true,
allow: [
'Window',
],
},
],
'no-undef-init': [
'warn',
],
'no-undefined': [
'error',
],
'no-useless-constructor': [
'warn',
],
'no-useless-escape': [
'off',
],
'no-useless-return': [
'error',
],
'no-var': [
'error',
],
'no-void': [
'off',
],
'no-with': [
'error',
],
'object-shorthand': [
'error',
'always',
],
'one-var': [
'error',
'never',
],
'operator-assignment': [
'warn',
'always',
],
'prefer-arrow-callback': [
'error',
],
'prefer-const': [
'error',
],
'prefer-object-has-own': [
'error',
],
'prefer-regex-literals': [
'error',
],
'prefer-template': [
'warn',
],
'no-prototype-builtins': 'off',
'@typescript-eslint/no-var-requires': [
'off',
],
'@stylistic/array-bracket-newline': [
'warn',
'consistent',
],
'@stylistic/array-bracket-spacing': [
'warn',
'never',
],
'@stylistic/arrow-parens': [
'warn',
'always',
],
'@stylistic/brace-style': [
'warn',
'stroustrup',
],
'@stylistic/comma-dangle': [
'warn',
'always-multiline',
],
'@stylistic/comma-spacing': [
'warn',
{
before: false,
after: true,
},
],
'@stylistic/comma-style': [
'error',
'last',
],
'@stylistic/dot-location': [
'error',
'property',
],
'@stylistic/function-call-argument-newline': [
'warn',
'consistent',
],
'@stylistic/function-paren-newline': [
'warn',
'consistent',
],
'@stylistic/indent': [
'warn',
4,
{
SwitchCase: 1,
ignoreComments: true,
ignoredNodes: ['TemplateLiteral > *'],
},
],
'@stylistic/key-spacing': [
'warn',
{
beforeColon: false,
afterColon: true,
},
],
'@stylistic/keyword-spacing': [
'warn',
{
before: true,
},
],
'@stylistic/linebreak-style': [
'error',
'unix',
],
'@stylistic/lines-between-class-members': [
'warn',
'always',
{
exceptAfterSingleLine: true,
},
],
'@stylistic/max-len': [
'warn',
{
code: 105,
ignoreComments: true,
ignoreTrailingComments: true,
ignoreUrls: true,
},
],
'@stylistic/multiline-ternary': [
'warn',
'always-multiline',
],
'@stylistic/new-parens': [
'error',
],
'@stylistic/no-mixed-operators': [
'warn',
],
'@stylistic/no-mixed-spaces-and-tabs': [
'error',
],
'@stylistic/no-multi-spaces': [
'error',
],
'@stylistic/no-tabs': [
'error',
],
'@stylistic/no-trailing-spaces': [
'error',
],
'@stylistic/no-whitespace-before-property': [
'warn',
],
'@stylistic/nonblock-statement-body-position': [
'error',
'below',
],
'@stylistic/object-curly-newline': [
'warn',
{
consistent: true,
},
],
'@stylistic/object-curly-spacing': [
'warn',
'always',
],
'@stylistic/operator-linebreak': [
'warn',
'after',
],
'@stylistic/padded-blocks': [
'error',
'never',
],
'@stylistic/padding-line-between-statements': [
'warn',
{
blankLine: 'always',
prev: '*',
next: 'return',
},
{
blankLine: 'always',
prev: [
'const',
'let',
'var',
],
next: '*',
},
{
blankLine: 'any',
prev: [
'const',
'let',
'var',
],
next: [
'const',
'let',
'var',
],
},
{
blankLine: 'always',
prev: [
'case',
'default',
],
next: '*',
},
],
'@stylistic/quote-props': [
'error',
'consistent-as-needed',
],
'@stylistic/quotes': [
'error',
'single',
{
avoidEscape: true,
},
],
'@stylistic/semi': [
'error',
'always',
],
'@stylistic/semi-spacing': [
'warn',
],
'@stylistic/space-before-blocks': [
'warn',
],
'@stylistic/space-before-function-paren': [
'warn',
'never',
],
'@stylistic/space-infix-ops': [
'warn',
],
'@stylistic/spaced-comment': [
'warn',
'always',
],
'@stylistic/switch-colon-spacing': [
'warn',
],
'@stylistic/wrap-regex': [
'warn',
],
},
});

View file

@ -1,3 +0,0 @@
import eslintConf from './eslint.config';
export default eslintConf;

File diff suppressed because it is too large Load diff

View file

@ -1,16 +0,0 @@
{
"name": "eslint-conf",
"version": "0.0.0",
"type": "module",
"exports": "./index.ts",
"devDependencies": {
"@eslint/js": "9.20.0",
"@stylistic/eslint-plugin": "3.1.0",
"eslint": "9.20.1",
"eslint-plugin-jsdoc": "50.6.3",
"jiti": "2.4.2",
"pkg-types": "1.3.1",
"typescript": "5.7.3",
"typescript-eslint": "8.24.1"
}
}

View file

@ -1,25 +0,0 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
// Env
"target": "ESNext",
"lib": [
"ESNext"
],
// Module
"module": "nodenext",
"moduleResolution": "bundler",
"baseUrl": ".",
// Emit
"noEmit": true,
"newLine": "LF",
// Interop
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
// Type Checking
"strict": true,
"noImplicitAny": false
}
}

View file

@ -1,10 +0,0 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "./tsconfig.base.json",
"includes": [
"*.ts",
"**/*.ts",
"*.js",
"**/*.js"
]
}

View file

@ -1,13 +0,0 @@
{
pkgs,
self,
...
}: let
inherit (pkgs.lib) getExe mapAttrs;
mkApp = pkg: {
program = getExe pkg;
type = "app";
};
in
mapAttrs (n: v: mkApp v) self.appsPackages.${pkgs.system}

View file

@ -1,3 +0,0 @@
use flake $FLAKE#subtitles-dev
(cd ../config; npm ci)
npm ci

View file

@ -1,17 +0,0 @@
{
buildApp,
ffmpeg-full,
...
}:
buildApp {
src = ./.;
npmDepsHash = "sha256-+NHetW6zNnJ8bubvuttwjnKGbXfwfcB0FIYpVvj7mjE=";
runtimeInputs = [
ffmpeg-full
];
meta.description = ''
Extract all `srt` subtitle files from a `mkv` video with the appropriate name.
'';
}

View file

@ -1,3 +0,0 @@
import eslintConf from 'eslint-conf';
export default eslintConf;

File diff suppressed because it is too large Load diff

View file

@ -1,21 +0,0 @@
{
"name": "extract-subs",
"version": "0.0.0",
"bin": "out/bin/app.cjs",
"type": "module",
"scripts": {
"build": "node_ver=$(node -v); esbuild src/app.ts --bundle --platform=node --target=\"node${node_ver:1:2}\" --outfile=out/bin/app.cjs"
},
"dependencies": {
"@types/fluent-ffmpeg": "2.1.27",
"fluent-ffmpeg": "2.1.3"
},
"devDependencies": {
"eslint-conf": "file:../config",
"@types/node": "22.10.10",
"esbuild": "0.24.2",
"eslint": "9.19.0",
"jiti": "2.4.2",
"typescript": "5.7.3"
}
}

View file

@ -1,157 +0,0 @@
import { spawnSync as spawn } from 'child_process';
import ffprobe from './ffprobe';
import { ISO6393To1 } from './lang-codes';
/* Types */
import { FfprobeStream } from 'fluent-ffmpeg';
const SPAWN_OPTS = {
stdio: [process.stdin, process.stdout, process.stderr],
};
/**
* These are the cli arguments
*
* @param videoPath the directory in which we want to sync the subtitles
* @param languages a comma-separated list of languages (3 letters) to sync the subtitles
*/
const video = process.argv[2];
const languages = process.argv[3]?.split(',');
// Global Vars
const subIndexes: number[] = [];
let videoPath: string;
let baseName: string;
/**
* Gets the relative path to the subtitle file of a ffmpeg stream.
*
* @param sub the stream of the subtitles to extract
* @returns the path of the subtitle file
*/
const getSubPath = (sub: FfprobeStream): string => {
const language = ISO6393To1.get(sub.tags.language);
const forced = sub.disposition?.forced === 0 ?
'' :
'.forced';
const hearingImpaired = sub.disposition?.hearing_impaired === 0 ?
'' :
'.sdh';
return `${baseName}${forced}.${language}${hearingImpaired}.srt`;
};
/**
* Removes all subtitles streams from the video file.
*/
const removeContainerSubs = (): void => {
spawn('mv', [
videoPath,
`${videoPath}.bak`,
], SPAWN_OPTS);
spawn('ffmpeg', [
'-i', `${videoPath}.bak`,
'-map', '0',
...subIndexes.map((i) => ['-map', `-0:${i}`]).flat(),
'-c', 'copy', videoPath,
], SPAWN_OPTS);
spawn('rm', [
`${videoPath}.bak`,
], SPAWN_OPTS);
};
/**
* Extracts a sub of a video file to a subtitle file.
*
* @param sub the stream of the subtitles to extract
*/
const extractSub = (sub: FfprobeStream): void => {
const subFile = getSubPath(sub);
spawn('ffmpeg', [
'-i', videoPath,
'-map', `0:${sub.index}`, subFile,
], SPAWN_OPTS);
subIndexes.push(sub.index);
};
/**
* Sorts the list of streams to only keep subtitles
* that can be extracted.
*
* @param lang the language of the subtitles
* @param streams the streams
* @returns the streams that represent subtitles
*/
const findSubs = (
lang: string,
streams: FfprobeStream[],
): FfprobeStream[] => {
const subs = streams.filter((s) => s.tags?.language &&
s.tags.language === lang &&
s.codec_type === 'subtitle');
const pgs = subs.filter((s) => s.codec_name === 'hdmv_pgs_subtitle');
// If we only have PGS subs, warn user
if (pgs.length === subs.length) {
console.warn(`No SRT subtitle tracks were found for ${lang}`);
}
// Remove PGS streams from subs
return subs.filter((s) => s.codec_name !== 'hdmv_pgs_subtitle');
};
/**
* Where the magic happens.
*/
const main = async(): Promise<void> => {
// Get rid of video extension
baseName = videoPath.split('/').at(-1)!.replace(/\.[^.]*$/, '');
// ffprobe the video file to see available sub tracks
const data = await ffprobe(videoPath);
if (!data?.streams) {
return;
}
// Check for languages wanted
languages.forEach((lang) => {
const subs = findSubs(lang, data.streams);
if (subs.length === 0) {
console.warn(`No subtitle tracks were found for ${lang}`);
return;
}
// Extract all subs
subs.forEach((sub) => {
extractSub(sub);
});
});
removeContainerSubs();
};
// Check if there are 2 params
if (video && languages) {
videoPath = video;
main();
}
else {
console.error('Error: no argument passed');
process.exit(1);
}

View file

@ -1,8 +0,0 @@
import Ffmpeg from 'fluent-ffmpeg';
export default (videoPath: string) => new Promise<Ffmpeg.FfprobeData>((resolve) => {
Ffmpeg.ffprobe(videoPath, (_e, data) => {
resolve(data);
});
});

View file

@ -1,373 +0,0 @@
export const ISO6391To3 = new Map([
['aa', 'aar'],
['ab', 'abk'],
['af', 'afr'],
['ak', 'aka'],
['am', 'amh'],
['ar', 'ara'],
['an', 'arg'],
['as', 'asm'],
['av', 'ava'],
['ae', 'ave'],
['ay', 'aym'],
['az', 'aze'],
['ba', 'bak'],
['bm', 'bam'],
['be', 'bel'],
['bn', 'ben'],
['bi', 'bis'],
['bo', 'bod'],
['bs', 'bos'],
['br', 'bre'],
['bg', 'bul'],
['ca', 'cat'],
['cs', 'ces'],
['ch', 'cha'],
['ce', 'che'],
['cu', 'chu'],
['cv', 'chv'],
['kw', 'cor'],
['co', 'cos'],
['cr', 'cre'],
['cy', 'cym'],
['da', 'dan'],
['de', 'deu'],
['dv', 'div'],
['dz', 'dzo'],
['el', 'ell'],
['en', 'eng'],
['eo', 'epo'],
['et', 'est'],
['eu', 'eus'],
['ee', 'ewe'],
['fo', 'fao'],
['fa', 'fas'],
['fj', 'fij'],
['fi', 'fin'],
['fr', 'fre'],
['fy', 'fry'],
['ff', 'ful'],
['gd', 'gla'],
['ga', 'gle'],
['gl', 'glg'],
['gv', 'glv'],
['gn', 'grn'],
['gu', 'guj'],
['ht', 'hat'],
['ha', 'hau'],
['sh', 'hbs'],
['he', 'heb'],
['hz', 'her'],
['hi', 'hin'],
['ho', 'hmo'],
['hr', 'hrv'],
['hu', 'hun'],
['hy', 'hye'],
['ig', 'ibo'],
['io', 'ido'],
['ii', 'iii'],
['iu', 'iku'],
['ie', 'ile'],
['ia', 'ina'],
['id', 'ind'],
['ik', 'ipk'],
['is', 'isl'],
['it', 'ita'],
['jv', 'jav'],
['ja', 'jpn'],
['kl', 'kal'],
['kn', 'kan'],
['ks', 'kas'],
['ka', 'kat'],
['kr', 'kau'],
['kk', 'kaz'],
['km', 'khm'],
['ki', 'kik'],
['rw', 'kin'],
['ky', 'kir'],
['kv', 'kom'],
['kg', 'kon'],
['ko', 'kor'],
['kj', 'kua'],
['ku', 'kur'],
['lo', 'lao'],
['la', 'lat'],
['lv', 'lav'],
['li', 'lim'],
['ln', 'lin'],
['lt', 'lit'],
['lb', 'ltz'],
['lu', 'lub'],
['lg', 'lug'],
['mh', 'mah'],
['ml', 'mal'],
['mr', 'mar'],
['mk', 'mkd'],
['mg', 'mlg'],
['mt', 'mlt'],
['mn', 'mon'],
['mi', 'mri'],
['ms', 'msa'],
['my', 'mya'],
['na', 'nau'],
['nv', 'nav'],
['nr', 'nbl'],
['nd', 'nde'],
['ng', 'ndo'],
['ne', 'nep'],
['nl', 'nld'],
['nn', 'nno'],
['nb', 'nob'],
['no', 'nor'],
['ny', 'nya'],
['oc', 'oci'],
['oj', 'oji'],
['or', 'ori'],
['om', 'orm'],
['os', 'oss'],
['pa', 'pan'],
['pi', 'pli'],
['pl', 'pol'],
['pt', 'por'],
['ps', 'pus'],
['qu', 'que'],
['rm', 'roh'],
['ro', 'ron'],
['rn', 'run'],
['ru', 'rus'],
['sg', 'sag'],
['sa', 'san'],
['si', 'sin'],
['sk', 'slk'],
['sl', 'slv'],
['se', 'sme'],
['sm', 'smo'],
['sn', 'sna'],
['sd', 'snd'],
['so', 'som'],
['st', 'sot'],
['es', 'spa'],
['sq', 'sqi'],
['sc', 'srd'],
['sr', 'srp'],
['ss', 'ssw'],
['su', 'sun'],
['sw', 'swa'],
['sv', 'swe'],
['ty', 'tah'],
['ta', 'tam'],
['tt', 'tat'],
['te', 'tel'],
['tg', 'tgk'],
['tl', 'tgl'],
['th', 'tha'],
['ti', 'tir'],
['to', 'ton'],
['tn', 'tsn'],
['ts', 'tso'],
['tk', 'tuk'],
['tr', 'tur'],
['tw', 'twi'],
['ug', 'uig'],
['uk', 'ukr'],
['ur', 'urd'],
['uz', 'uzb'],
['ve', 'ven'],
['vi', 'vie'],
['vo', 'vol'],
['wa', 'wln'],
['wo', 'wol'],
['xh', 'xho'],
['yi', 'yid'],
['yo', 'yor'],
['za', 'zha'],
['zh', 'zho'],
['zu', 'zul'],
]);
export const ISO6393To1 = new Map([
['aar', 'aa'],
['abk', 'ab'],
['afr', 'af'],
['aka', 'ak'],
['amh', 'am'],
['ara', 'ar'],
['arg', 'an'],
['asm', 'as'],
['ava', 'av'],
['ave', 'ae'],
['aym', 'ay'],
['aze', 'az'],
['bak', 'ba'],
['bam', 'bm'],
['bel', 'be'],
['ben', 'bn'],
['bis', 'bi'],
['bod', 'bo'],
['bos', 'bs'],
['bre', 'br'],
['bul', 'bg'],
['cat', 'ca'],
['ces', 'cs'],
['cha', 'ch'],
['che', 'ce'],
['chu', 'cu'],
['chv', 'cv'],
['cor', 'kw'],
['cos', 'co'],
['cre', 'cr'],
['cym', 'cy'],
['dan', 'da'],
['deu', 'de'],
['div', 'dv'],
['dzo', 'dz'],
['ell', 'el'],
['eng', 'en'],
['epo', 'eo'],
['est', 'et'],
['eus', 'eu'],
['ewe', 'ee'],
['fao', 'fo'],
['fas', 'fa'],
['fij', 'fj'],
['fin', 'fi'],
['fre', 'fr'],
['fry', 'fy'],
['ful', 'ff'],
['gla', 'gd'],
['gle', 'ga'],
['glg', 'gl'],
['glv', 'gv'],
['grn', 'gn'],
['guj', 'gu'],
['hat', 'ht'],
['hau', 'ha'],
['hbs', 'sh'],
['heb', 'he'],
['her', 'hz'],
['hin', 'hi'],
['hmo', 'ho'],
['hrv', 'hr'],
['hun', 'hu'],
['hye', 'hy'],
['ibo', 'ig'],
['ido', 'io'],
['iii', 'ii'],
['iku', 'iu'],
['ile', 'ie'],
['ina', 'ia'],
['ind', 'id'],
['ipk', 'ik'],
['isl', 'is'],
['ita', 'it'],
['jav', 'jv'],
['jpn', 'ja'],
['kal', 'kl'],
['kan', 'kn'],
['kas', 'ks'],
['kat', 'ka'],
['kau', 'kr'],
['kaz', 'kk'],
['khm', 'km'],
['kik', 'ki'],
['kin', 'rw'],
['kir', 'ky'],
['kom', 'kv'],
['kon', 'kg'],
['kor', 'ko'],
['kua', 'kj'],
['kur', 'ku'],
['lao', 'lo'],
['lat', 'la'],
['lav', 'lv'],
['lim', 'li'],
['lin', 'ln'],
['lit', 'lt'],
['ltz', 'lb'],
['lub', 'lu'],
['lug', 'lg'],
['mah', 'mh'],
['mal', 'ml'],
['mar', 'mr'],
['mkd', 'mk'],
['mlg', 'mg'],
['mlt', 'mt'],
['mon', 'mn'],
['mri', 'mi'],
['msa', 'ms'],
['mya', 'my'],
['nau', 'na'],
['nav', 'nv'],
['nbl', 'nr'],
['nde', 'nd'],
['ndo', 'ng'],
['nep', 'ne'],
['nld', 'nl'],
['nno', 'nn'],
['nob', 'nb'],
['nor', 'no'],
['nya', 'ny'],
['oci', 'oc'],
['oji', 'oj'],
['ori', 'or'],
['orm', 'om'],
['oss', 'os'],
['pan', 'pa'],
['pli', 'pi'],
['pol', 'pl'],
['por', 'pt'],
['pus', 'ps'],
['que', 'qu'],
['roh', 'rm'],
['ron', 'ro'],
['run', 'rn'],
['rus', 'ru'],
['sag', 'sg'],
['san', 'sa'],
['sin', 'si'],
['slk', 'sk'],
['slv', 'sl'],
['sme', 'se'],
['smo', 'sm'],
['sna', 'sn'],
['snd', 'sd'],
['som', 'so'],
['sot', 'st'],
['spa', 'es'],
['sqi', 'sq'],
['srd', 'sc'],
['srp', 'sr'],
['ssw', 'ss'],
['sun', 'su'],
['swa', 'sw'],
['swe', 'sv'],
['tah', 'ty'],
['tam', 'ta'],
['tat', 'tt'],
['tel', 'te'],
['tgk', 'tg'],
['tgl', 'tl'],
['tha', 'th'],
['tir', 'ti'],
['ton', 'to'],
['tsn', 'tn'],
['tso', 'ts'],
['tuk', 'tk'],
['tur', 'tr'],
['twi', 'tw'],
['uig', 'ug'],
['ukr', 'uk'],
['urd', 'ur'],
['uzb', 'uz'],
['ven', 've'],
['vie', 'vi'],
['vol', 'vo'],
['wln', 'wa'],
['wol', 'wo'],
['xho', 'xh'],
['yid', 'yi'],
['yor', 'yo'],
['zha', 'za'],
['zho', 'zh'],
['zul', 'zu'],
]);

View file

@ -1,10 +0,0 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "../config/tsconfig.base.json",
"includes": [
"*.ts",
"**/*.ts",
"*.js",
"**/*.js"
]
}

View file

@ -1,15 +0,0 @@
{
writeShellApplication,
jq,
pandoc,
...
}:
writeShellApplication {
name = "gen-docs";
runtimeInputs = [jq pandoc];
text = builtins.readFile ./script.sh;
meta.description = ''
Generates the READMEs in this repository from nix attributes.
'';
}

View file

@ -1,13 +0,0 @@
attr: selfPath: let
inherit (builtins) mapAttrs replaceStrings;
modules = import "${selfPath}/${attr}" {description = true;};
trimNewlines = s: replaceStrings ["\n"] [" "] s;
in {
attrs =
mapAttrs (_: v: {
desc = trimNewlines v;
})
modules;
}

View file

@ -1,12 +0,0 @@
configs: let
inherit (builtins) mapAttrs replaceStrings;
trimNewlines = s: replaceStrings ["\n"] [" "] s;
in {
attrs =
mapAttrs (_: v: {
roleDesc = trimNewlines (v.config.meta.roleDescription or "");
hwDesc = trimNewlines (v.config.meta.hardwareDescription or "");
})
configs;
}

View file

@ -1,13 +0,0 @@
x: let
inherit (builtins) currentSystem mapAttrs removeAttrs replaceStrings;
trimNewlines = s: replaceStrings ["\n"] [" "] s;
packages = removeAttrs x.${currentSystem} ["default"];
in {
attrs =
mapAttrs (_: v: {
desc = trimNewlines (v.meta.description or "");
homepage = v.meta.homepage or "";
})
packages;
}

View file

@ -1,31 +0,0 @@
attr: selfPath: let
inherit (builtins) currentSystem getFlake mapAttrs removeAttrs replaceStrings;
self = getFlake selfPath;
scopes = import "${selfPath}/${attr}" {description = true;};
trimNewlines = s: replaceStrings ["\n"] [" "] s;
in {
attrs =
mapAttrs (n: v: {
desc = trimNewlines v;
packages = let
scopePkgs = removeAttrs self.${attr}.${currentSystem}.${n} [
"buildFirefoxXpiAddon"
"callPackage"
"newScope"
"override"
"overrideDerivation"
"overrideScope"
"packages"
"recurseForDerivations"
];
in
mapAttrs (_: pkg: {
desc = trimNewlines (pkg.meta.description or "");
homepage = pkg.meta.homepage or "";
})
scopePkgs;
})
scopes;
}

View file

@ -1,43 +0,0 @@
substituteDerivs() {
echo '' | pandoc --metadata-file <(
nix eval \
--impure \
--json \
"$FLAKE"#"$1" \
--apply "import \"$FLAKE/apps/gen-docs/$3.nix\"" |
jq -r
) -t markdown --template "$FLAKE/apps/gen-docs/templates/$2.md" -o "$FLAKE/$2/README.md"
}
substituteAttrs() {
echo '' | pandoc --metadata-file <(
nix eval \
--impure \
--json \
--expr "\"$FLAKE\"" \
--apply "(import \"$FLAKE/apps/gen-docs/getAttrsMeta.nix\") \"$1\"" |
jq -r
) -t markdown --template "$FLAKE/apps/gen-docs/templates/$1.md" -o "$FLAKE/$1/README.md"
}
substituteScopes() {
echo '' | pandoc --metadata-file <(
nix eval \
--impure \
--json \
--expr "\"$FLAKE\"" \
--apply "(import \"$FLAKE/apps/gen-docs/getScopesMeta.nix\") \"$1\"" |
jq -r
) -t markdown --template "$FLAKE/apps/gen-docs/templates/$1.md" -o "$FLAKE/$1/README.md"
}
substituteDerivs "appsPackages" "apps" "getPackageMeta"
substituteDerivs "nixosConfigurations" "configurations" "getConfigMeta"
substituteDerivs "devShells" "devShells" "getPackageMeta"
substituteDerivs "packages" "packages" "getPackageMeta"
substituteAttrs "modules"
substituteAttrs "homeManagerModules"
substituteAttrs "overlays"
substituteScopes "scopedPackages"

View file

@ -1,11 +0,0 @@
# Apps
This directory contains every derivations for apps exposed by this flake.
## List of my apps found in `self.apps`
| Name | Description |
| ---- | ----------- |
$for(attrs/pairs)$
| `$it.key$` | $it.value.desc/nowrap$ |
$endfor$

View file

@ -1,13 +0,0 @@
# NixosConfigurations
This directory contains every device's main configuration file, their `hardware-configuration.nix` and some custom modules
unique to them.
## List of my devices
| Name | Model / Specs | Description |
| --------- | ------------- | ------------------------------------------------------------------------------------------------ |
| `android` | OnePlus 9 Pro | [Nix-On-Droid](https://github.com/nix-community/nix-on-droid) configuration for my OnePlus 9 Pro |
$for(attrs/pairs)$
| `$it.key$` | $it.value.hwDesc/nowrap$ | $it.value.roleDesc/nowrap$ |
$endfor$

View file

@ -1,11 +0,0 @@
# DevShells
This directory contains every derivations for devShells exposed by this flake.
## List of my devShells found in `self.devShells`
| Name | Description |
| ---- | ----------- |
$for(attrs/pairs)$
| `$it.key$` | $it.value.desc/nowrap$ |
$endfor$

View file

@ -1,11 +0,0 @@
# HomeManagerModules
This directory contains every home-manager modules exposed by this flake.
## List of my home-manager modules found in `self.homeManagerModules`
| Name | Description |
| ---- | ----------- |
$for(attrs/pairs)$
| `$it.key$` | $it.value.desc/nowrap$ |
$endfor$

View file

@ -1,11 +0,0 @@
# NixosModules
This directory contains every modules for NixOS exposed by this flake.
## List of my modules found in `self.nixosModules`
| Name | Description |
| ---- | ----------- |
$for(attrs/pairs)$
| `$it.key$` | $it.value.desc/nowrap$ |
$endfor$

View file

@ -1,11 +0,0 @@
# Overlays
This directory contains every overlay exposed by this flake.
## List of my overlays found in `self.overlays`
| Name | Description |
| ---- | ----------- |
$for(attrs/pairs)$
| `$it.key$` | $it.value.desc/nowrap$ |
$endfor$

View file

@ -1,11 +0,0 @@
# Packages
This directory contains every derivations for packages exposed by this flake.
## List of my packages found in `self.packages`
| Name | Description | Homepage |
| ---- | ----------- | -------- |
$for(attrs/pairs)$
| `$it.key$` | $it.value.desc/nowrap$ | $it.value.homepage/nowrap$ |
$endfor$

View file

@ -1,18 +0,0 @@
# ScopedPackages
This directory contains every package scopes exposed by this flake.
## List of my package scopes found in `self.scopedPackages`
$for(attrs/pairs)$
### $it.key$
$it.value.desc/nowrap$
| Name | Description | Homepage |
| ---- | ----------- | -------- |
$for(it.value.packages/pairs)$
| `$it.key$` | $it.value.desc/nowrap$ | $it.value.homepage/nowrap$ |
$endfor$
$endfor$

View file

@ -1,16 +0,0 @@
{
inputs,
pkgs,
...
}: let
inherit (pkgs.lib) listToAttrs nameValuePair;
buildApp = attrs: (pkgs.callPackage ./buildApp.nix ({} // inputs // attrs));
callPackage = file: pkgs.callPackage file ({inherit buildApp;} // inputs);
in
listToAttrs (map (x: nameValuePair x (callPackage ./${x})) [
"extract-subs"
"gen-docs"
"pin-inputs"
"update-sources"
])

View file

@ -1,3 +0,0 @@
use flake $FLAKE#node
(cd ../config; npm ci)
npm ci

View file

@ -1,11 +0,0 @@
{buildApp, ...}:
buildApp {
src = ./.;
npmDepsHash = "sha256-qNTgtT+x1O1jMWYgs8pXy3fUJKHBnf9adhR9nD5V7TY=";
runtimeInputs = [];
meta.description = ''
Takes a list of inputs to pin to their current rev in `flake.lock`.
'';
}

View file

@ -1,3 +0,0 @@
import eslintConf from 'eslint-conf';
export default eslintConf;

File diff suppressed because it is too large Load diff

View file

@ -1,18 +0,0 @@
{
"name": "pin-inputs",
"version": "0.0.0",
"bin": "out/bin/app.cjs",
"type": "module",
"scripts": {
"build": "node_ver=$(node -v); esbuild src/app.ts --bundle --platform=node --target=\"node${node_ver:1:2}\" --outfile=out/bin/app.cjs"
},
"devDependencies": {
"eslint-conf": "file:../config",
"@types/node": "22.12.0",
"esbuild": "0.24.2",
"eslint": "9.19.0",
"jiti": "2.4.2",
"pkg-types": "1.3.1",
"typescript": "5.7.3"
}
}

View file

@ -1,62 +0,0 @@
import { readFileSync, writeFileSync } from 'fs';
export const replaceInFile = (replace: RegExp, replacement: string, file: string) => {
const fileContents = readFileSync(file);
const replaced = fileContents.toString().replace(replace, replacement);
writeFileSync(file, replaced);
};
/* Constants */
const FLAKE = process.env.FLAKE;
if (!FLAKE) {
console.error('Environment variable FLAKE not found');
process.exit(1);
}
const FLAKE_LOCK = JSON.parse(readFileSync(`${FLAKE}/flake.lock`, 'utf8')).nodes;
const INPUT_REVS = new Map<string, string>();
Object.entries(FLAKE_LOCK).forEach(([key, val]) => {
if (key !== 'root') {
// eslint-disable-next-line
INPUT_REVS.set(key, (val as any).locked.rev);
}
});
const INPUTS = process.argv.slice(2);
/**
* Gets the commit hash of the specified input in this flake.
*
* @param input the name of the input
* @returns the commit hash
*/
const getCurrentRev = (input: string): string => {
if (!INPUT_REVS.has(input)) {
throw new Error(`Input ${input} could not be found.`);
}
return INPUT_REVS.get(input) as string;
};
INPUTS.forEach((input) => {
try {
const inputsFile = `${FLAKE}/inputs/default.nix`;
const rev = getCurrentRev(input);
const msg = ['FIX', 'ME'].join('');
replaceInFile(
new RegExp(`(\\n[ ]*)${input} =.*\\n.*\\n.*`),
`$&\n$1 # ${msg}: $1 rev = "${rev}";`,
inputsFile,
);
}
catch (e) {
console.error((e as Error).message);
}
});

View file

@ -1,10 +0,0 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "../config/tsconfig.base.json",
"includes": [
"*.ts",
"**/*.ts",
"*.js",
"**/*.js"
]
}

View file

@ -1,3 +0,0 @@
use flake $FLAKE#node
(cd ../config; npm ci)
npm ci

View file

@ -1,32 +0,0 @@
{
buildApp,
callPackage,
curl,
findutils,
go,
jq,
nix-update,
nodejs_latest,
prefetch-npm-deps,
...
}:
buildApp {
src = ./.;
npmDepsHash = "sha256-2cWxVTCOEJOg2eBv+xX/mvr6MUX+UJQ8JlkoObD6+Uc=";
runtimeInputs = [
curl
findutils
go
jq
nix-update
nodejs_latest
prefetch-npm-deps
(callPackage ../../modules/docker/updateImage.nix {})
];
meta.description = ''
Updates all derivation sources in this repository and
generates a commit message for the changes made.
'';
}

View file

@ -1,3 +0,0 @@
import eslintConf from 'eslint-conf';
export default eslintConf;

File diff suppressed because it is too large Load diff

View file

@ -1,18 +0,0 @@
{
"name": "update-sources",
"version": "0.0.0",
"bin": "out/bin/app.cjs",
"type": "module",
"scripts": {
"build": "node_ver=$(node -v); esbuild src/app.ts --bundle --platform=node --target=\"node${node_ver:1:2}\" --outfile=out/bin/app.cjs"
},
"devDependencies": {
"eslint-conf": "file:../config",
"@types/node": "22.13.4",
"esbuild": "0.25.0",
"eslint": "9.20.1",
"jiti": "2.4.2",
"pkg-types": "1.3.1",
"typescript": "5.7.3"
}
}

View file

@ -1,188 +0,0 @@
import { spawnSync } from 'node:child_process';
import { writeFileSync } from 'node:fs';
import { parseArgs } from './lib';
import { updateDocker } from './docker';
import { updateFirefoxAddons } from '././firefox';
import { updateFlakeInputs } from './flake';
import updateNodeModules from './node-modules';
import {
runNixUpdate,
updateCaddyPlugins,
updateVuetorrent,
} from './misc';
/* Constants */
const FLAKE = process.env.FLAKE;
if (!FLAKE) {
console.error('Env var FLAKE not found');
process.exit(1);
}
const args = parseArgs();
const main = async() => {
if (args['c'] || args['custom-sidebar']) {
console.log(runNixUpdate('scopedPackages', 'lovelace-components', 'custom-sidebar'));
}
if (args['cp'] || args['caddy-plugins']) {
console.log(updateCaddyPlugins());
}
if (args['d'] || args['docker']) {
console.log(updateDocker());
}
if (args['f'] || args['firefox']) {
console.log(updateFirefoxAddons());
}
if (args['h'] || args['homepage']) {
console.log(runNixUpdate('homepage'));
}
if (args['i'] || args['inputs']) {
console.log(updateFlakeInputs());
}
if (args['j'] || args['jmusicbot']) {
console.log(runNixUpdate('jmusicbot'));
}
if (args['m'] || args['material-rounded-theme']) {
console.log(runNixUpdate('scopedPackages', 'lovelace-components', 'material-rounded-theme'));
}
if (args['n'] || args['node_modules']) {
console.log(await updateNodeModules());
}
if (args['p'] || args['pam-fprint-grosshack']) {
console.log(runNixUpdate('pam-fprint-grosshack'));
}
if (args['ph'] || args['protonhax']) {
console.log(runNixUpdate('protonhax'));
}
if (args['s'] || args['some-sass-language-server']) {
console.log(runNixUpdate('some-sass-language-server'));
}
if (args['t'] || args['trash-d']) {
console.log(runNixUpdate('trash-d'));
}
if (args['v'] || args['vuetorrent']) {
console.log(updateVuetorrent());
}
if (args['a'] || args['all']) {
// Update this first because of nix run cmd
const firefoxOutput = updateFirefoxAddons();
console.log(firefoxOutput);
const flakeOutput = updateFlakeInputs();
console.log(flakeOutput);
const dockerOutput = updateDocker();
console.log(dockerOutput);
const nodeModulesOutput = await updateNodeModules();
console.log(nodeModulesOutput);
const vuetorrentOutput = updateVuetorrent();
console.log(vuetorrentOutput);
const caddyPluginsOutput = updateCaddyPlugins();
console.log(caddyPluginsOutput);
// nix-update executions
let nixUpdateOutputs = '';
const updatePackage = (
attr: string,
scope?: string,
scopeAttr?: string,
): void => {
const execution = runNixUpdate(attr, scope, scopeAttr);
nixUpdateOutputs += execution.stdout;
console.log(execution.stderr);
console.log(execution.stdout);
};
updatePackage('homepage');
updatePackage('jmusicbot');
updatePackage('pam-fprint-grosshack');
updatePackage('protonhax');
updatePackage('some-sass-language-server');
updatePackage('trash-d');
updatePackage('scopedPackages', 'lovelace-components', 'custom-sidebar');
updatePackage('scopedPackages', 'lovelace-components', 'material-rounded-theme');
spawnSync('nixFastBuild', [], {
shell: true,
stdio: [process.stdin, process.stdout, process.stderr],
});
const indentOutput = (output: string): string => {
return ` ${output.split('\n').join('\n ')}`;
};
const output = [
'chore: update sources\n\n',
];
if (flakeOutput.length > 5) {
output.push(`Flake Inputs:\n${indentOutput(flakeOutput)}\n\n`);
}
if (dockerOutput.length > 5) {
output.push(`Docker Images:\n${indentOutput(dockerOutput)}\n`);
}
if (firefoxOutput.length > 5) {
output.push(`Firefox Addons:\n${indentOutput(firefoxOutput)}\n\n`);
}
if (nodeModulesOutput.length > 5) {
output.push(`Node modules:\n${indentOutput(nodeModulesOutput)}\n`);
}
if (vuetorrentOutput.length > 5) {
output.push(`Misc Sources:\n${indentOutput(vuetorrentOutput)}\n\n`);
}
if (caddyPluginsOutput.length > 5) {
output.push(`Caddy Plugins:\n${indentOutput(caddyPluginsOutput)}\n\n`);
}
if (nixUpdateOutputs.length > 5) {
output.push(`nix-update executions:\n${indentOutput(nixUpdateOutputs)}\n`);
}
if (args['f']) {
writeFileSync(args['f'] as string, output.join(''));
}
else {
console.log(output.join(''));
}
}
spawnSync('alejandra', ['-q', FLAKE], { shell: true });
};
main();

View file

@ -1,33 +0,0 @@
import { readdirSync } from 'node:fs';
import { spawnSync } from 'node:child_process';
/* Constants */
const FLAKE = process.env.FLAKE;
const updateImages = (imagePath: string): string | undefined => {
console.log(`Updating ${imagePath.split('/').at(-1)} images`);
const out = spawnSync('updateImages', [imagePath], { shell: true }).stdout.toString();
if (!out.startsWith('# Locked')) {
return out;
}
};
export const updateDocker = () => {
let updates = '';
updates += updateImages(`${FLAKE}/configurations/nos/modules/jellyfin`) ?? '';
updates += updateImages(`${FLAKE}/configurations/homie/modules/home-assistant/netdaemon`) ?? '';
const DIR = `${FLAKE}/configurations/nos/modules/docker`;
readdirSync(DIR, { withFileTypes: true, recursive: true }).forEach((path) => {
if (path.name === 'compose.nix') {
updates += updateImages(path.parentPath) ?? '';
}
});
return updates;
};

View file

@ -1,61 +0,0 @@
import { spawnSync } from 'node:child_process';
import { readFileSync } from 'node:fs';
/* Constants */
const FLAKE = process.env.FLAKE;
export const updateFirefoxAddons = () => {
console.log('Updating firefox addons using mozilla-addons-to-nix');
const DIR = `${FLAKE}/scopedPackages/firefox-addons`;
const GENERATED_FILE = `${DIR}/generated-firefox-addons.nix`;
const SLUGS = `${DIR}/addons.json`;
const nameMap = Object.fromEntries([...JSON.parse(readFileSync(SLUGS, 'utf-8'))]
.map((addon) => [addon.slug, addon.pname || addon.slug]));
const nixExpr = `'
x: let
inherit (builtins) attrValues filter hasAttr isAttrs map;
in
map (d: d.name) (filter (y:
isAttrs y &&
hasAttr "type" y &&
y.type == "derivation") (attrValues x))
'`;
const OLD_VERS = Object.fromEntries([...JSON.parse(spawnSync('nix', [
'eval',
'.#scopedPackages.x86_64-linux.firefoxAddons',
'--apply',
nixExpr,
'--json',
], { shell: true }).stdout.toString())]
.map((p) => {
const pname = p.replace(/-[0-9].*$/, '');
return [pname, p.replace(`${pname}-`, '')];
})
.filter((pinfo) => pinfo[0] !== 'frankerfacez'));
const NEW_VERS = Object.fromEntries(spawnSync(
'nix',
['run', 'sourcehut:~rycee/mozilla-addons-to-nix',
SLUGS, GENERATED_FILE],
{ shell: true },
).stdout
.toString()
.split('\n')
.map((p) => {
const pinfo = p.replace('Fetched ', '').split(' ');
return [nameMap[pinfo[0]], pinfo[2]];
}));
return Object.keys(OLD_VERS)
.sort()
.filter((pname) => OLD_VERS[pname] !== NEW_VERS[pname])
.map((pname) => `${pname}: ${OLD_VERS[pname]} -> ${NEW_VERS[pname]}`)
.join('\n');
};

View file

@ -1,45 +0,0 @@
import { spawnSync } from 'node:child_process';
/* Constants */
const FLAKE = process.env.FLAKE;
export const updateFlakeInputs = () => {
const output = spawnSync(
`git restore flake.lock &> /dev/null; nix flake update --flake ${FLAKE}` +
' |& grep -v "warning: updating lock file" |& grep -v "unpacking"',
[],
{ shell: true },
).stdout
.toString()
// Add an extra blank line between inputs
.split('\n•')
// Filter out some inputs
.filter((input) => ![
'systems',
'flake-compat',
'flake-utils',
'flake-parts',
'treefmt-nix',
'lib-aggregate',
'lib-aggregate/nixpkgs-lib',
'nix-gaming/umu',
'nix-github-actions',
'pre-commit-hooks',
].some((inputName) => input.startsWith(` Updated input '${inputName}'`)))
.join('\n\n•')
// help readability of git revs
.split('\n')
.map((l) => l
.replace(
/\/(.{40})\?narHash=sha256[^']*(.*)/,
(_, backref1, backref2) => `${backref2} rev: ${backref1}`,
)
.replace(
/\?ref.*&rev=(.{40})[^'&]*(.*)/,
(_, backref1, backref2) => `${backref2} rev: ${backref1}`,
))
.join('\n');
return output;
};

View file

@ -1,43 +0,0 @@
import { spawnSync } from 'node:child_process';
import { readFileSync, writeFileSync } from 'node:fs';
export const parseArgs = () => {
const args = {} as Record<string, unknown>;
let lastFlag: string | null = null;
for (let i = 2; i < process.argv.length; ++i) {
const arg = process.argv[i];
if (arg.toString().startsWith('-')) {
lastFlag = arg.toString().replace(/^-{1,2}/, '');
args[lastFlag] = true;
}
else if (lastFlag) {
args[lastFlag] = arg;
lastFlag = null;
}
else {
console.error(`Could not parse args: ${arg.toString()}`);
}
}
return args;
};
export const parseFetchurl = (url: string) => JSON.parse(spawnSync(
'nix', ['store', 'prefetch-file', '--refresh', '--json',
'--hash-type', 'sha256', url, '--name', '"escaped"'], { shell: true },
).stdout.toString()).hash;
export const replaceInFile = (replace: RegExp, replacement: string, file: string) => {
const fileContents = readFileSync(file);
const replaced = fileContents.toString().replace(replace, replacement);
writeFileSync(file, replaced);
};
export const npmRun = (args: string[], workspaceDir: string) => spawnSync(
'npm', args, { cwd: workspaceDir },
).stdout.toString();

View file

@ -1,161 +0,0 @@
import { writeFileSync } from 'node:fs';
import { spawnSync } from 'node:child_process';
import { parseFetchurl, replaceInFile } from './lib';
/* Constants */
const FLAKE = process.env.FLAKE;
const genVueText = (
version: string,
hash: string,
url: string,
) => `# This file was autogenerated. DO NOT EDIT!
{
version = "${version}";
url = "${url}";
hash = "${hash}";
}
`;
export const updateVuetorrent = () => {
const FILE = `${FLAKE}/configurations/nos/modules/qbittorrent/vuetorrent.nix`;
const OLD_VERSION = JSON.parse(spawnSync('nix',
['eval', '-f', FILE, '--json'],
{ shell: true }).stdout.toString()).version;
const VERSION = JSON.parse(spawnSync('curl',
['-s', 'https://api.github.com/repos/VueTorrent/VueTorrent/releases/latest'],
{ shell: true }).stdout.toString()).tag_name.replace('v', '');
const URL = `https://github.com/VueTorrent/VueTorrent/releases/download/v${VERSION}/vuetorrent.zip`;
const HASH = parseFetchurl(URL);
const fileText = genVueText(VERSION, HASH, URL);
writeFileSync(FILE, fileText);
return OLD_VERSION !== VERSION ? `Vuetorrent: ${OLD_VERSION} -> ${VERSION}` : '';
};
const getAttrVersion = (attr: string): string => spawnSync('nix',
['eval', '--raw', `${FLAKE}#${attr}.version`],
{ shell: true }).stdout.toString();
export const runNixUpdate = (
attr: string,
scope?: string,
scopeAttr?: string,
): { stdout: string, stderr: string } => {
const getJsonArray = (jsonObj: string) => Array(JSON.parse(jsonObj))[0].slice(1).join(' ');
const realAttr = scope ? `${attr}.x86_64-linux.${scope}.${scopeAttr}` : attr;
const OLD_VERSION = getAttrVersion(realAttr);
const execOptions = spawnSync(
`nix eval --json ${FLAKE}#${realAttr}.updateScript`,
[],
{ shell: true, cwd: FLAKE },
);
const options = execOptions.status === 0 ?
execOptions.stdout.toString().startsWith('[') ?
getJsonArray(execOptions.stdout.toString()) :
'-u' :
'';
const execution = spawnSync(
`nix-update --flake ${realAttr} ${options} --write-commit-message >(head -n 1 -) > /dev/null`,
[],
{ shell: true, cwd: FLAKE },
);
const NEW_VERSION = getAttrVersion(realAttr);
return {
stdout: OLD_VERSION !== NEW_VERSION ?
scope ?
execution.stdout.toString().replaceAll(`${attr}.x86_64-linux.${scope}.`, '') :
execution.stdout.toString() :
'',
stderr: execution.stderr.toString(),
};
};
const genPluginsText = (
plugins: Record<string, { url: string, version: string }>,
) => `# This file was autogenerated. DO NOT EDIT!
{
plugins = {
${Object.entries(plugins)
.map(([key, value]) => `
${key} = {
url = "${value.url}";
version = "${value.version}";
};
`)
.join('')}
};
hash = "";
}
`;
export const updateCaddyPlugins = () => {
let updates = '';
const dir = `${FLAKE}/configurations/cluster/modules/caddy`;
// Setup workspace
spawnSync(
[
'rm -rf /tmp/update-caddy',
'mkdir -p /tmp/update-caddy',
'cd /tmp/update-caddy || exit 1',
'go mod init temp',
].join('; '),
[],
{ shell: true, cwd: '/tmp' },
);
const plugins = JSON.parse(spawnSync('nix',
['eval', '-f', `${dir}/plugins.nix`, '--json'],
{ shell: true }).stdout.toString()).plugins as Record<string, { url: string, version: string }>;
// Get most recent versions of plugins
Object.entries(plugins).forEach(([key, value]) => {
const NEW_VERSION = spawnSync([
'go mod init temp > /dev/null',
`go get ${value.url} > /dev/null`,
`grep '${value.url}' go.mod`,
].join('; '), [], { shell: true, cwd: '/tmp/update-caddy' })
.stdout
.toString()
.trim()
.replace(' // indirect', '')
.split(' ')[1];
if (plugins[key].version !== NEW_VERSION) {
updates += `${key}: ${plugins[key].version} -> ${NEW_VERSION}`;
plugins[key].version = NEW_VERSION;
}
});
writeFileSync(`${dir}/plugins.nix`, genPluginsText(plugins));
// Get new hash
const caddyPkgAttr = 'nixosConfigurations.thingone.config.services.caddy.package';
const NEW_HASH = spawnSync(
`nix build "$FLAKE#${caddyPkgAttr}" |& sed -n 's/.*got: *//p'`,
[],
{ shell: true },
).stdout.toString().trim();
replaceInFile(/hash = ".*";/, `hash = "${NEW_HASH}";`, `${dir}/plugins.nix`);
return updates;
};

View file

@ -1,103 +0,0 @@
import { readPackageJSON, writePackageJSON } from 'pkg-types';
import { accessSync, constants, existsSync } from 'node:fs';
import { spawnSync } from 'node:child_process';
import { replaceInFile, npmRun } from './lib';
/* Constants */
const FLAKE = process.env.FLAKE as string;
const updatePackageJson = async(workspaceDir: string, updates: object) => {
const currentPackageJson = await readPackageJSON(`${workspaceDir}/package.json`);
const outdated = JSON.parse(npmRun(['outdated', '--json'], workspaceDir));
const updateDeps = (deps: string) => {
Object.keys(currentPackageJson[deps]).forEach((dep) => {
const versions = outdated[dep];
const current = versions?.wanted || versions?.current;
if (!current) {
return;
}
if (current !== versions.latest) {
updates[dep] = `${current} -> ${versions.latest}`;
}
currentPackageJson[deps][dep] = versions.latest;
});
};
if (currentPackageJson.dependencies) {
updateDeps('dependencies');
}
if (currentPackageJson.devDependencies) {
updateDeps('devDependencies');
}
await writePackageJSON(`${workspaceDir}/package.json`, currentPackageJson);
};
const prefetchNpmDeps = (workspaceDir: string): string => {
npmRun(['update', '--package-lock-only'], workspaceDir);
return spawnSync(
'prefetch-npm-deps',
[`${workspaceDir}/package-lock.json`],
).stdout.toString().replace('\n', '');
};
export default async() => {
console.log('Updating node modules');
const updates = {};
const packages = spawnSync('find', [FLAKE, '-name', 'package.json']).stdout.toString().split('\n')
.filter((f) => f !== '')
.filter((f) => ![
'.direnv',
'node_modules',
'results',
].some((dirName) => f.includes(dirName)));
for (const path of packages) {
console.log(path);
try {
accessSync(path, constants.R_OK | constants.W_OK);
const parentPath = path.replace('/package.json', '');
await updatePackageJson(parentPath, updates);
if (existsSync(`${parentPath}/default.nix`)) {
const hash = prefetchNpmDeps(parentPath);
replaceInFile(
/npmDepsHash = ".*";/,
`npmDepsHash = "${hash}";`,
`${parentPath}/default.nix`,
);
}
// Make sure we update the apps' config package-lock.json
if (parentPath.includes('apps/config')) {
npmRun(['i'], parentPath);
}
}
catch (e) {
console.warn(`Could not write to ${path}`);
console.warn(e);
}
}
return Object.entries(updates)
.map(([key, dep]) => `${key}: ${dep}`)
.join('\n');
};

View file

@ -1,10 +0,0 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "../config/tsconfig.base.json",
"includes": [
"*.ts",
"**/*.ts",
"*.js",
"**/*.js"
]
}

1
config/eww/README.md Normal file
View file

@ -0,0 +1 @@
inspired from: https://github.com/AlphaTechnolog/dotfiles/tree/openbox

View file

@ -0,0 +1 @@
always open this widget last

View file

@ -0,0 +1,60 @@
(defwidget closer []
(eventbox :onclick "$EWW_PATH/close-opened.sh && eww close closer")
)
(defwindow closer :monitor 0
:geometry (geometry :width "100%"
:height "100%")
:stacking "overlay"
:focusable false
(closer :window "")
)
(defwidget closer-notif []
(eventbox :onclick "$EWW_PATH/notif-toggle.sh off")
)
(defwindow closer-notif1 :monitor 0
:geometry (geometry :width "1360px"
:height "1200px")
:stacking "overlay"
:focusable false
:exclusive "ignore"
(closer-notif)
)
(defwindow closer-notif2 :monitor 0
:geometry (geometry :width "100%"
:height "200px"
:y "1060px")
:stacking "overlay"
:focusable false
:exclusive "ignore"
(closer-notif)
)
(defwindow closer-notif3 :monitor 0
:geometry (geometry :width "100%"
:height "60px")
:stacking "overlay"
:focusable false
:exclusive "ignore"
(closer-notif)
)
(defwindow closer-notif4 :monitor 0
:geometry (geometry :width "60px"
:height "100%"
:x "1860px")
:stacking "overlay"
:focusable false
:exclusive "ignore"
(closer-notif)
)
(defwidget on-release-fix []
(eventbox :onclick "eww close on-release-fix")
)
(defwindow on-release-fix :monitor 0
:geometry (geometry :width "100%"
:height "100%"
)
:stacking "overlay"
:exclusive "ignore"
(on-release-fix)
)

32
config/eww/colors.scss Normal file
View file

@ -0,0 +1,32 @@
$darkbg: #0b0d16;
$bg: rgba(40, 42, 54, 0.8); //rgba(69, 71, 90, 0.3); #0d0f18;
$bgfull: rgb(40, 42, 54);
$contrastbg: rgba(189, 147, 249, 0.8);
$bgSecondary: #11131c;
$bgSecondaryAlt: #a5b6cf;
$fg: #a5b6cf;
$fgDim: #a5b6cf;
$watermelon: #dd6777;
// Aliases
$background: $bg;
$backgroundSecondary: $bgSecondary;
$backgroundSecondaryAlt: $bgSecondaryAlt;
$foreground: $fg;
$foregroundDim: $fgDim;
$black: #151720;
$dimblack: #1a1c25;
$lightblack: #262831;
$red: #dd6777;
$blue: #86aaec;
$cyan: #93cee9;
$blue-desaturated: #93cee9;
$magenta: #c296eb;
$purple: #c296eb;
$green: #90ceaa;
$aquamarine: #90ceaa;
$yellow: #ecd3a0;
$accent: $blue;
$javacafeMagenta: #c296eb;
$javacafeBlue: #86aaec;

75
config/eww/date/date.scss Normal file
View file

@ -0,0 +1,75 @@
.date {
background-color: $bg;
color: $fg;
border-radius: 30px;
border: 2px solid $contrastbg;
}
.timebox {
margin: 30px 0px;
.time-container {
.content {
font-family: Product Sans;
font-weight: bolder;
font-size: 60px;
}
.divider {
margin: 8px 15px;
padding: 0px 1px;
background: linear-gradient($red, $magenta, $blue, $cyan);
}
}
.date-container {
font-family: Product Sans;
margin-top: 2px;
}
}
.cal-box {
font-family: Product Sans;
background-color: $bg;
border-radius: 30px;
padding: 0 1rem .2rem;
color: $fg;
background-color: $bgfull;
border-bottom: 2px solid $contrastbg;
border-top: 2px solid $contrastbg;
margin: 0px 12px 18px 12px;
.cal {
background-color: inherit;
padding: .5rem .10rem 0rem;
margin-left: 10px;
border-radius: 30px;
& > * {
border: solid 0px transparent;
}
&.highlight {
padding: 10rem;
}
}
}
calendar:selected {
color: $cyan;
}
calendar.header {
color: $cyan;
font-weight: bold;
}
calendar.button {
color: $cyan;
}
calendar.highlight {
color: $green;
font-weight: bold;
}
calendar:indeterminate {
color: $lightblack;
}

63
config/eww/date/date.yuck Normal file
View file

@ -0,0 +1,63 @@
(defwidget divider []
(box :class "divider"
:orientation "v"
:space-evenly true)
)
(defwidget time []
(box :class "timebox"
:orientation "v"
:space-evenly false
(box :class "time-container"
:orientation "h"
:space-evenly false
:halign "center"
:valign "center"
(label :text "${lithour}" :class "content")
(divider)
(label :text "${litmin}" :class "content")
)
(box :class "date-container"
:orientation "h"
:space-evenly true
:halign "center"
(label :text "${completeday}")
)
)
)
(defwidget cal []
(box :class "cal-box"
:orientation "v"
:space-evenly false
(calendar :class "cal"
:day calendar_day
:month calendar_month
:year calendar_year)
)
)
(defwidget date []
(box :class "date"
:orientation "v"
:space-evenly false
(time)
(cal)
)
)
(defvar date-visible false)
(defwindow date-reveal
:monitor 0
:stacking "overlay"
:geometry (geometry :x "70px"
:y "8px"
:width "0px" ; automatically generated
:height "0px" ; automatically generated
:anchor "top right")
(revealer
:transition "crossfade"
:reveal date-visible
:duration anim_duration
(date)))

10
config/eww/eww.scss Normal file
View file

@ -0,0 +1,10 @@
* {
all: unset;
}
@import "colors.scss";
@import "date/date.scss";
@import "powermenu/powermenu.scss";
@import "playerinfo/playerinfo.scss";
@import "quick-settings/quick-settings.scss";
@import "traybuttons/traybuttons.scss";

7
config/eww/eww.yuck Normal file
View file

@ -0,0 +1,7 @@
(include "variables.yuck")
(include "date/date.yuck")
(include "powermenu/powermenu.yuck")
(include "playerinfo/playerinfo.yuck")
(include "closer/closer.yuck")
(include "quick-settings/quick-settings.yuck")
(include "traybuttons/traybuttons.yuck")

View file

@ -0,0 +1,90 @@
.playerinfo {
padding: 10px;
min-width: 400px;
border-radius: 30px;
border-top: 2px solid $contrastbg;
border-bottom: 2px solid $contrastbg;
transition: background 250ms;
.top {
font-size: 23px;
}
.metadata {
.title{
font-weight: 500;
transition: text 250ms;
}
.artist{
font-weight: 400;
font-size: 15px;
transition: text 250ms;
}
}
.bottom {
font-size: 30px;
}
.pausebutton {
transition: background 250ms;
padding: 14px 16px;
font-size: 15px;
}
.playing {
transition: all ease .2s;
border-radius: 15px;
label {
padding-left: 4px;
}
}
.paused {
border-radius: 26px;
transition: all ease .2s;
padding: 14px 14px 14px 18px;
}
}
.previousbutton,
.nextbutton,
.shuffle,
.repeat {
border-radius: 100%;
transition: background-color 200ms;
&:hover {
border-radius: 100%;
background-color: rgba(127, 132, 156, 0.4);
transition: background-color 200ms;
}
}
.repeat {
label {
padding-right: 8px;
}
}
.song-pos {
scale {
highlight {
margin: 0px;
border-radius: 2em;
}
trough {
background-color: #363847;
border-radius: 2em;
}
slider {
margin: -8px;
min-height: 20px;
border-radius: 10px;
box-shadow: rgba(0, 0, 0, 0.25) 0px 54px 55px, rgba(0, 0, 0, 0.12) 0px -12px 30px, rgba(0, 0, 0, 0.12) 0px 4px 6px, rgba(0, 0, 0, 0.17) 0px 12px 13px, rgba(0, 0, 0, 0.09) 0px -3px 5px;
transition: background-color 0.5s ease-in-out;
}
slider:hover {
background-color: #303240;
transition: background-color 0.5s ease-in-out;
}
}
}

View file

@ -0,0 +1,124 @@
(defpoll player :interval "1s" "echo Spot")
(defpoll music_cover :interval "1s" "$EWW_PATH/music.sh cover") ;done
(defvar music_accent "rgb(0,0,0)") ;done
(defvar button_accent "rgb(0,0,0)") ;done
(defvar button_text "rgb(255,255,255)") ;done
(defpoll music_status :interval "1s" "playerctl -p Spot status")
(defpoll title :interval "1s" "playerctl -p Spot metadata title")
(defpoll artist :interval "1s" "playerctl -p Spot metadata artist")
(defvar button_height "42")
(defpoll shuffle_status :interval "1s" "playerctl -p Spot shuffle")
(defpoll repeat_icon :interval "1s" "$EWW_PATH/music.sh loop_status")
(defvar song_pos "0")
(defpoll song_length :interval "1s" "$EWW_PATH/music.sh length")
(defvar get_pos "true")
(defwidget playerinfo []
(centerbox :class "playerinfo"
:style "background: radial-gradient(circle, rgba(0, 0, 0, 0.4) 30%, ${music_accent}), url(\"${music_cover}\");
background-size: cover;
background-position: center;"
:orientation "v"
(box :class "top"
:halign "start"
:valign "start"
:style "color: ${button_accent};"
"${player == 'Spot' ? '' : '爵' }"
)
(box :class "center"
:orientation "h"
:space-evenly false
(box :class "metadata"
:orientation "v"
:halign "start"
:valign "center"
:hexpand true
(label :limit-width 25 :halign "start" :text title :class "title")
(label :limit-width 25 :halign "start" :text artist :class "artist")
)
(centerbox :orientation "v"
(label)
(eventbox :class "pausebutton ${music_status == 'Playing' ? 'playing' : 'paused'}"
:halign "left"
:style "background-color: ${button_accent};
color: ${button_text};"
:onclick "playerctl -p Spot play-pause"
:cursor "pointer"
:onhover "eww update button_height=41"
:onhoverlost "eww update button_height=42"
(label :text "${music_status == 'Playing' ? ' ' : ''}"
:width button_height
:height button_height
)
)
(label)
)
)
(box :class "bottom"
:style "color: ${button_accent};"
:space-evenly false
:spacing 0
(eventbox :valign "end"
:halign "start"
:onclick "playerctl -p Spot previous & $EWW_PATH/music.sh cover"
:class "previousbutton"
:width 40
:cursor "pointer"
"󰒮"
)
(eventbox :cursor "pointer"
:class "song-pos"
:hexpand true
:onhover "eww update get_pos=false"
:onhoverlost "eww update get_pos=true"
(scale :value song_pos
:min 0
:max song_length
:orientation "h"
:onchange "playerctl -p Spot position {}"
:css "highlight { background-color: ${button_accent}; }
slider { background-color: ${button_accent}; }
trough { background-color: rgba(${button_accent}, 0.4); }"
)
)
(box :valign "end"
:halign "end"
(eventbox :onclick "playerctl -p Spot next & $EWW_PATH/music.sh cover"
:class "nextbutton"
:width 40
:cursor "pointer"
"󰒭"
)
(eventbox :onclick "playerctl -p Spot shuffle toggle"
:class "shuffle"
:width 40
:cursor "pointer"
"${shuffle_status == 'On' ? '󰒝' : '󰒞'}"
)
(eventbox :onclick "$EWW_PATH/music.sh loop"
:class "repeat"
:width 40
:cursor "pointer"
"${repeat_icon}"
)
)
)
)
)
(defwindow playerinfo
:monitor 0
:stacking "overlay"
:exclusive "ignore"
:focusable "false"
:geometry (geometry :x "800px"
:y "10px"
:width "0px"
:height "0px"
:anchor "top left"
)
(playerinfo)
)

View file

@ -0,0 +1,28 @@
.powermenu {
background-color: $bg;
color: $fg;
padding: 20px;
font-family: MesloLGS NF;
/*font-family: Iosevka Nerd Font;*/
font-size: 70px;
border-radius: 30px;
border: 2px solid $contrastbg;
button {
border-radius: 12px;
min-width: 80px;
transition: all ease .2s;
&:hover { background-color: $bgSecondary; }
&:active { background-color: $bgSecondary; }
.content {
border-radius: 4px;
padding: 0px 15px 0px 15px;
}
}
.shutdown { color: $red; }
.reboot { color: $magenta; }
.logout { color: $yellow; }
}
.powermenu-clickhandler {
background-color: black;
}

View file

@ -0,0 +1,55 @@
(defwidget powermenu []
(box :class "powermenu"
:orientation "h"
:space-evenly true
:spacing 20
(button :class "shutdown"
:onclick "systemctl poweroff"
(label :text "襤" :class "content")
)
(button :class "reboot"
:onclick "systemctl reboot"
(label :text "勒" :class "content")
)
(button :class "logout"
:onclick "hyprctl dispatch exit"
(label :text "" :class "content")
)
)
)
(defwidget powermenu-clickhandler []
(button :class "powermenu-clickhandler"
:onclick "eww close powermenu powermenu-clickhandler"
""
)
)
(defwindow powermenu-clickhandler
:monitor 0
:geometry (geometry :x "0px"
:y "0px"
:width "100%"
:height "100%"
:anchor "center")
:wm-ignore true
(powermenu-clickhandler)
)
(defvar powermenu-visible false)
(defwindow powermenu-reveal
:monitor 0
:stacking "overlay"
:geometry (geometry :x "0px"
:y "0px"
:width "500px"
:height "150px"
:anchor "center")
(revealer
:transition "crossfade"
:reveal powermenu-visible
:duration anim_duration
(powermenu)
)
)

View file

@ -0,0 +1,190 @@
.quick-settings-smol {
font-size: 2px;
min-height: 52px;
min-width: 36px;
padding: 0px 0px 0px 0px;
background-color: $bg;
color: rgba(0,0,0,0);
border: 2px solid $contrastbg;
border-bottom: none;
border-top-right-radius: 80px;
border-top-left-radius: 80px;
border-bottom-left-radius: 0px;
border-bottom-right-radius: 0px;
}
.quick-settings-logo {
font-size: 24px;
min-height: 36px;
min-width: 36px;
padding: 0px 0px 0px 0px;
background-color: rgba(0,0,0,0);
color: #CBA6F7;
border-radius: 80px;
border: 2px solid rgba(0,0,0,0);
transition: background-color 0.5s ease-in-out;
}
.quick-settings-logo:hover, .quick-settings-logo:active {
background-color: rgba(127, 132, 156, 0.4);
transition: background-color 0.5s ease-in-out;
}
.quick-settings {
font-size: 30px;
min-width: 500px;
padding: 0px 0px 0px 0px;
background-color: $bg;
border-top-right-radius: 0px;
border-top-left-radius: 30px;
border-bottom-left-radius: 30px;
border-bottom-right-radius: 30px;
border: 2px solid $contrastbg;
}
.title {
font-size: 22px;
margin-top: 30px;
}
.grid-label {
font-size: 30px;
margin-left: 15px;
margin-right: 10px;
min-width: 50px;
}
.sub-label {
font-size: 14px;
margin-top: -10px;
margin-left: 0px;
margin-bottom: 10px;
padding: 3px;
border: 2px solid $contrastbg;
border-top-right-radius: 20px;
border-top-left-radius: 10px;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 20px;
min-width: 106px;
background: #1b1b1b;
}
.grid-chev {
margin-left: 0px;
font-size: 40px;
margin-right: 5px;
}
.button-grid {
font-size: 10px;
min-height: 160px;
min-width: 470px;
background-color: $bgfull;
border-top: 2px solid $contrastbg;
border-bottom: 2px solid $contrastbg;
border-radius: 15px;
margin-top: 30px;
}
.button-row {
min-height: 70px;
min-width: 450px;
margin-left: 20px;
}
.grid-button {
min-height: 65px;
min-width: 70px;
margin: 5px;
}
.left-part {
background: #1b1b1b;
border-top-left-radius: 15px;
border-bottom-left-radius: 15px;
border-left: 2px solid $contrastbg;
border-top: 2px solid $contrastbg;
border-bottom: 2px solid $contrastbg;
transition: all 0.5s ease-in-out;
}
.right-part {
background: #1b1b1b;
border-top-right-radius: 30px;
border-bottom-right-radius: 30px;
border-right: 2px solid $contrastbg;
border-top: 2px solid $contrastbg;
border-bottom: 2px solid $contrastbg;
transition: all 0.5s ease-in-out;
}
.right-part:hover, .right-part:active {
color: $contrastbg;
border: 2px solid $contrastbg;
border-top-left-radius: 7px;
border-bottom-left-radius: 7px;
transition: all 0.5s ease-in-out;
}
.left-part:hover, .left-part:active {
color: $contrastbg;
border: 2px solid $contrastbg;
border-top-right-radius: 7px;
border-bottom-right-radius: 7px;
transition: all 0.5s ease-in-out;
}
.player {
margin-top: 6px;
min-height: 220px;
opacity: 0;
}
.slider-box {
min-height: 100px;
min-width: 470px;
background-color: $bgfull;
border-top: 2px solid $contrastbg;
border-bottom: 2px solid $contrastbg;
border-radius: 15px;
margin-top: 30px;
margin-bottom: 20px;
.slider-label {
font-size: 30px;
min-width: 30px;
}
scale {
min-height: 55px;
min-width: 400px;
margin-left: 18px;
margin-right: 20px;
highlight {
margin: 0px;
background-color: #79659f;
border-radius: 2em;
}
trough {
background-color: #363847;
border-radius: 2em;
}
slider {
margin: -4px;
min-width: 20px;
min-height: 20px;
background: #3e4153;
border-radius: 100%;
box-shadow: rgba(0, 0, 0, 0.25) 0px 54px 55px, rgba(0, 0, 0, 0.12) 0px -12px 30px, rgba(0, 0, 0, 0.12) 0px 4px 6px, rgba(0, 0, 0, 0.17) 0px 12px 13px, rgba(0, 0, 0, 0.09) 0px -3px 5px;
transition: background-color 0.5s ease-in-out;
}
slider:hover {
background-color: #303240;
transition: background-color 0.5s ease-in-out;
}
}
}

View file

@ -0,0 +1,360 @@
(defvar showqs false)
(defvar showplayer false)
(defwidget quick-settings-smol []
(box :class "quick-settings-smol"
:orientation "h"
(label :text "  ")
)
)
(defwindow quick-settings-smol-reveal
:monitor 0
:stacking "overlay"
:exclusive "ignore"
:geometry (geometry :x "5px"
:y "10px"
:width "0px"
:height "0px"
:anchor "top right"
)
(revealer
:transition "crossfade"
:reveal showqs
:duration anim_duration
(quick-settings-smol)
)
)
(defvar qs-run-off "false")
(defwidget quick-settings-logo []
(eventbox :class "quick-settings-logo"
:onclick "$EWW_PATH/run.sh '$EWW_PATH/qs-toggle.sh off' qs-run-off &"
:cursor "pointer"
:onhover "eww update qs-run-off=true"
:onhoverlost "eww update qs-run-off=false"
(box :class "quick-settings-logo"
:orientation "h"
(label :text "  ")
)
)
)
(defwindow quick-settings-logo-reveal
:monitor 0
:stacking "overlay"
:exclusive "ignore"
:geometry (geometry :x "5px"
:y "10px"
:width "0px"
:height "0px"
:anchor "top right"
)
(revealer
:transition "crossfade"
:reveal showqs
:duration anim_duration
(quick-settings-logo)
)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar expand_player "false")
(defwidget quick-settings []
(box :orientation "v"
:space-evenly false
(box :class "quick-settings"
:orientation "v"
:space-evenly false
(label :text "Control Center"
:class "title"
:xalign 0.04
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Button Grid
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(box :class "button-grid"
:orientation "v"
:valign "start"
:width 0
:height 0
:halign "center"
:space-evenly false
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Row ONE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(box :class "button-row"
:orientation "h"
:space-evenly true
:width 0
:height 0
:halign "center"
:style "margin-top: 15px;
margin-bottom: 7px"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(box :class "grid-button"
:orientation "h"
:space-evenly false
:width 0
:height 0
(eventbox :class "left-part"
:cursor "pointer"
:onclick "$EWW_PATH/network.sh toggle"
(label :text " ${network_icon} "
:class "grid-label"
)
)
(eventbox :class "right-part"
:cursor "pointer"
:onclick "nm-connection-editor &"
(label :text " " :class "grid-chev")
)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(box :class "grid-button"
:orientation "h"
:space-evenly false
:width 0
:height 0
(eventbox :class "left-part"
:cursor "pointer"
:onclick "$EWW_PATH/bluetooth.sh toggle"
(label :text " ${bluetooth_icon} "
:class "grid-label"
)
)
(eventbox :class "right-part"
:cursor "pointer"
:onclick "blueberry &"
(label :text " " :class "grid-chev")
)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(box :class "grid-button"
:orientation "h"
:space-evenly false
:width 0
:height 0
(eventbox :class "left-part"
:cursor "pointer"
:onclick "$EWW_PATH/network.sh toggle-radio"
(label :text "${network_radio == 'on' ? '󰀝 ' : '󱡻 '}"
:class "grid-label"
)
)
(eventbox :class "right-part"
:cursor "pointer"
:onclick "notify-send 'set this up moron'"
(label :text " "
:class "grid-chev"
)
)
)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; SUB ROW
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(box :orientation "h"
:space-evenly true
:spacing 34
:width 0
:height 0
:halign "center"
(label :text "${network_ssid}"
:class "sub-label"
:width 0
:height 0
:xalign 0.4
:limit-width 12
)
(label :text "${bluetooth_dev}"
:class "sub-label"
:width 0
:height 0
:xalign 0.4
:limit-width 12
)
(label :text ""
:class ""
:width 0
:height 0
:xalign 0.4
:limit-width 12
)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Row TWO
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(box :class "button-row"
:orientation "h"
:space-evenly true
:width 0
:height 0
:halign "center"
:style "margin-top: 7px;
margin-bottom: 15px;"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(box :class "grid-button"
:orientation "h"
:space-evenly false
:width 0
:height 0
(eventbox :class "left-part"
:cursor "pointer"
:onclick "swayosd --output-volume mute-toggle"
(label :text " ${volume_icon} "
:class "grid-label"
)
)
(eventbox :class "right-part"
:cursor "pointer"
:onclick "pavucontrol &"
(label :text " " :class "grid-chev")
)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(box :class "grid-button"
:orientation "h"
:space-evenly false
:width 0
:height 0
(eventbox :class "left-part"
:cursor "pointer"
:onclick "$EWW_PATH/mic.sh toggle-muted"
(label :text " ${mic_icon} "
:class "grid-label"
)
)
(eventbox :class "right-part"
:cursor "pointer"
:onclick "pavucontrol &"
(label :text " " :class "grid-chev")
)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(box :class "grid-button"
:orientation "h"
:space-evenly false
:width 0
:height 0
(eventbox :class "left-part"
:cursor "pointer"
:onclick "$LOCK_PATH/lock.sh &"
(label :text " 󰌾 "
:class "grid-label"
)
)
(eventbox :class "right-part"
:cursor "pointer"
:onclick "$EWW_PATH/open.sh powermenu"
(label :text " " :class "grid-chev")
)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
)
)
(box :class "slider-box"
:orientation "v"
:space-evenly true
:spacing 0
:width 0
:height 0
:halign "center"
(box :class "slider"
:orientation "h"
:valign "start"
:halign "center"
:width 0
:height 0
:space-evenly false
(label :text "${volume_icon}" :class "slider-label")
(scale :value volume_value
:onchange "$EWW_PATH/volume.sh set {}"
:min 0
:max 101
:height 0
:width 0
)
)
(box :class "slider"
:orientation "h"
:valign "start"
:halign "center"
:width 0
:height 0
:space-evenly false
(label :text " ${br_icon} " :class "slider-label" :style "margin-left: 6px;
margin-right: -6px")
(scale :value br
:onchange "$EWW_PATH/brightness.sh set {}"
:min 0
:max 256
:height 0
:width 0
)
)
)
(centerbox :orientation "h"
:style "margin-bottom: 10px;"
(label)
(revealer :reveal showplayer
(eventbox :cursor "pointer"
:onclick "${expand_player == 'true' ? 'eww update expand_player=false' : 'eww update expand_player=true'}"
"${expand_player == 'true' ? ' ' : ' ' }"
)
)
(label)
)
)
(revealer :reveal expand_player
:transition "slidedown"
(box :class "player"
:style "${expand_player == 'true' ? 'opacity: 1; transition: opacity ${anim_duration}' :
'opacity: 0; transition: opacity ${anim_duration}'}"
(playerinfo)
)
)
)
)
(defwindow quick-settings-reveal
:monitor 0
:stacking "overlay"
:geometry (geometry :x "5px"
:y "7px"
:width "0px"
:height "0px"
:anchor "top right"
)
(revealer
:transition "crossfade"
:reveal showqs
:duration anim_duration
(quick-settings)
)
)

35
config/eww/scripts/bluetooth.sh Executable file
View file

@ -0,0 +1,35 @@
#!/usr/bin/env bash
FILE="$HOME/.config/.bluetooth"
get_device() {
if [[ $(bluetoothctl devices Connected) != "" ]]; then
bluetoothctl devices Connected | awk '{ for (i = 3; i <= NF; i++) { printf("%s ", $i) } printf("\n") }'
else
echo "Disconnected"
fi
}
get_state() {
if [[ "$(rfkill list | grep -A 1 hci0 | grep -o no)" == "no" ]]; then
eww update bluetooth_icon=" 󰂯 "
echo " 󰂯 " > "$FILE"
else
eww update bluetooth_icon=" 󰂲 "
echo " 󰂲 " > "$FILE"
fi
}
[[ "$1" == "device" ]] && get_device
if [[ "$1" == "toggle" ]]; then
rfkill toggle bluetooth
get_state
fi
if [[ $1 == "icon" ]]; then
while true; do
get_state
tail "$FILE"
sleep 1
done
fi

View file

@ -0,0 +1,46 @@
#!/usr/bin/env bash
get_icon () {
val=$(brightnessctl get)
if [ "$val" -le 3 ]; then
eww update br_icon=" "
elif [ "$val" -le 38 ]; then
eww update br_icon=" "
elif [ "$val" -le 77 ]; then
eww update br_icon=" "
elif [ "$val" -le 115 ]; then
eww update br_icon=" "
elif [ "$val" -le 153 ]; then
eww update br_icon=" "
elif [ "$val" -le 191 ]; then
eww update br_icon=" "
elif [ "$val" -le 230 ]; then
eww update br_icon=" "
else
eww update br_icon=" "
fi
}
if [[ $1 == "br" ]]; then
brightnessctl get
fi
if [[ $1 == "icon" ]]; then
while true; do
get_icon
sleep 1
done
fi
if [[ $1 == "set" ]]; then
brightnessctl set "$2"
get_icon
fi

View file

@ -0,0 +1,20 @@
#!/usr/bin/env bash
# Store the output of the command in an array, keeping only lines with '*'
readarray -t array <<< "$(eww windows | grep '^\*')"
# Remove the '*' from each element
for ((i=0; i<${#array[@]}; i++))
do
array[i]=${array[i]#'*'}
done
# Close every window except permanent ones
for element in "${array[@]}"
do
[[ "$element" != "left-bar" ]] &&
[[ "$element" != "notif-panel" ]] &&
[[ "$element" != "quick-settings-toggle" ]] &&
[[ "$element" != "playerinfo" ]] &&
eww close "$element"
done

46
config/eww/scripts/heart.sh Executable file
View file

@ -0,0 +1,46 @@
#!/usr/bin/env bash
FILE="$HOME/.config/.heart"
toggle() {
if grep -q 󰣐 "$FILE"; then
eww update heart-ts=false
echo  > "$FILE"
else
eww update heart-ts=true
echo 󰣐 >> "$FILE"
fi
}
[[ "$1" == "toggle" ]] && toggle
startup() {
(
if [[ ! -f "$FILE" ]]; then
echo 󰣐 > "$FILE"
fi
if [[ ! -f "$HOME/.config/.bluetooth" ]]; then
echo 󰂲 > "$FILE"
fi
if grep -q 󰂲 "$HOME/.config/.bluetooth"; then
rfkill block bluetooth
fi
"$HYPR_PATH"/osk-toggle.sh getState &
"$EWW_PATH"/on-release.sh &
"$EWW_PATH"/music.sh accents &
input-emulator start mouse -n &
if grep -q 󰣐 "$FILE"; then
sleep 0.9 &&
eww update heart-ts=true
fi
) &
tail -f "$FILE"
}
[[ "$1" == "startup" ]] && startup

30
config/eww/scripts/mic.sh Executable file
View file

@ -0,0 +1,30 @@
#!/usr/bin/env bash
SOURCE="@DEFAULT_SOURCE@"
is_muted () {
pactl get-source-mute $SOURCE | awk '{print $2}'
}
get_icon () {
if [[ $(is_muted) == "yes" ]]; then
echo " 󰍭"
else
echo " 󰍬"
fi
}
if [[ $1 == "icon" ]]; then
while true; do
sleep 0.01
get_icon
done
fi
if [[ $1 == "muted" ]]; then
is_muted
fi
if [[ $1 == "toggle-muted" ]]; then
swayosd --input-volume mute-toggle
fi

87
config/eww/scripts/music.sh Executable file
View file

@ -0,0 +1,87 @@
#!/usr/bin/env bash
loop() {
loop_status=$(playerctl -p Spot loop)
case $loop_status in
"None" )
playerctl -p Spot loop Playlist
eww update repeat_icon="󰑖"
;;
"Track" )
playerctl -p Spot loop None
eww update repeat_icon="󰑗"
;;
"Playlist" )
playerctl -p Spot loop Track
eww update repeat_icon="󰑘"
;;
* )
echo "Unknown loop status."
;;
esac
}
loop_status() {
loop_status=$(playerctl -p Spot loop)
case $loop_status in
"None" )
eww update repeat_icon="󰑗"
;;
"Track" )
eww update repeat_icon="󰑘"
;;
"Playlist" )
eww update repeat_icon="󰑖"
;;
* )
echo "Unknown loop status."
;;
esac
}
get_length() {
if [[ $(eww get get_pos) == "true" ]]; then
eww update song_pos="$(playerctl -p Spot position)"
fi
eww update song_length="$(echo "$(playerctl -p Spot metadata mpris:length)/1000000" | bc -l)"
}
get_accents() {
accents="$(coloryou /tmp/cover.jpg | sed 's/,//g' | sed 's/}//' | sed 's/'\''//g')"
music_accent=$(echo "$accents" | awk '{ print $2 }')
eww update music_accent="$music_accent"
button_accent=$(echo "$accents" | awk '{ print $4 }')
eww update button_accent="$button_accent"
button_text=$(echo "$accents" | awk '{ print $6 }')
eww update button_text="$button_text"
}
get_cover() {
existing_file="/tmp/cover.jpg"
new_image_url=$(playerctl -p Spot metadata mpris:artUrl)
existing_hash=$(md5sum "$existing_file" | awk '{print $1}')
# Download the new image only if the hashes are different
if [[ "$(wget -qO- "$new_image_url" | md5sum | awk '{print $1}')" != "$existing_hash" ]]; then
wget -qO "$existing_file" "$new_image_url"
get_accents
fi
if [[ -s "/tmp/cover.jpg" ]]; then
eww update showplayer=true
echo "/tmp/cover.jpg"
else
eww update showplayer=false
echo "randomfile"
fi
}
[[ "$1" == "accents" ]] && get_accents
[[ "$1" == "loop" ]] && loop
[[ "$1" == "loop_status" ]] && loop_status
[[ "$1" == "length" ]] && get_length
[[ "$1" == "cover" ]] && get_cover

53
config/eww/scripts/network.sh Executable file
View file

@ -0,0 +1,53 @@
#!/usr/bin/env bash
get_ssid() {
if nmcli -t -f NAME c show --active | grep -v lo; then
true
else
echo "Disconnected"
fi
}
get_state() {
if [[ "$(rfkill list | grep -A 1 LAN | grep -o no)" == "no" ]]; then
eww update network_icon=" 󰖩 "
else
eww update network_icon=" 󰖪 "
fi
}
[[ "$1" == "ssid" ]] && get_ssid
if [[ "$1" == "toggle" ]]; then
rfkill toggle wlan
get_state
fi
if [[ $1 == "icon" ]]; then
while true; do
get_state
sleep 1
done
fi
radio_status () {
radio_status=$(nmcli radio wifi)
if [[ $radio_status == "enabled" ]]; then
echo "on"
else
echo "off"
fi
}
if [[ $1 == "radio-status" ]]; then
radio_status
fi
if [[ $1 == "toggle-radio" ]]; then
stat=$(radio_status)
if [[ $stat == "on" ]]; then
nmcli radio wifi off
else
nmcli radio wifi on
fi
fi

View file

@ -0,0 +1,29 @@
#!/usr/bin/env bash
on() {
# open notif panel
swaync-client -op
# open closers to close when outside control center
eww open closer-notif1
eww open closer-notif2
eww open closer-notif3
eww open closer-notif4
eww close notif-panel; eww open notif-panel &&
eww update notif-panel-state=true
}
off() {
swaync-client -cp
eww update notif-panel-state=false
eww close closer-notif1
eww close closer-notif2
eww close closer-notif3
eww close closer-notif4
}
[[ "$1" == "on" ]] && on
[[ "$1" == "off" ]] && off

30
config/eww/scripts/notif.sh Executable file
View file

@ -0,0 +1,30 @@
#!/usr/bin/env bash
state () {
if [[ $(hyprctl layers | grep swaync-control-center) == "" ]]; then
if [[ $(eww get notif-panel-state) == "true" ]]; then
eww update notif-panel-state=false
fi
fi
}
icon () {
COUNT=$(swaync-client -c)
if [[ $(swaync-client -D) == "true" ]]; then
echo " 󱏨"
elif [[ $COUNT == "0" ]]; then
echo "$COUNT 󰂜"
else
echo "$COUNT 󰂚"
fi
state
}
if [[ $1 == "icon" ]]; then
while true; do
sleep 0.01
icon
done
fi

View file

@ -0,0 +1,22 @@
#!/usr/bin/env bash
FILE="$HOME/.config/.on-release"
function run() {
echo "can_run" > "$FILE"
}
while IFS='$\n' read -r line; do
if [[ $(echo "$line" | grep TOUCH_UP) != "" ]]; then
run
if [[ $(echo "$line" | grep '1 (1)') != "" ]]; then
eww update cancel_touch=false
fi
elif [[ $(echo "$line" | grep release) != "" ]]; then
run
elif [[ $(echo "$line" | grep 'TOUCH_DOWN.*1 (1)') != "" ]]; then
eww update cancel_touch=true
else
echo "other" > "$FILE"
fi
done < <(stdbuf -oL libinput debug-events)

7
config/eww/scripts/open.sh Executable file
View file

@ -0,0 +1,7 @@
#!/usr/bin/env bash
eww open closer &&
WINDOW="$1"
eww open "$WINDOW"-reveal
eww update "$WINDOW"-visible=true

20
config/eww/scripts/qs-toggle.sh Executable file
View file

@ -0,0 +1,20 @@
#!/usr/bin/env bash
on () {
eww open closer &&
eww open quick-settings-reveal;
eww open quick-settings-smol-reveal;
eww open quick-settings-logo-reveal;
eww update showqs=true
}
off () {
eww update showqs=false
eww close quick-settings-reveal
eww close quick-settings-smol-reveal
eww close quick-settings-logo-reveal
}
[[ "$1" == "on" ]] && on
[[ "$1" == "off" ]] && off

22
config/eww/scripts/run.sh Executable file
View file

@ -0,0 +1,22 @@
#!/usr/bin/env bash
FILE="$HOME/.config/.on-release"
SCRIPT="$1"
VAR="$2"
function run() {
if [[ $(eww get "$VAR") == "true" ]]; then
if [[ $(eww get cancel_touch) == "false" ]]; then
bash -c "$SCRIPT"
fi
else
eww open on-release-fix
sleep 0.1
input-emulator mouse button left
fi
exit 0
}
while IFS='$\n' read -r line; do
[[ $(grep "can_run" "$FILE") != "" ]] && run
done < <(stdbuf -oL tail -f "$FILE")

90
config/eww/scripts/volume.sh Executable file
View file

@ -0,0 +1,90 @@
#!/usr/bin/env bash
SINK="@DEFAULT_SINK@"
percentage () {
local val=$(echo $1 | tr '%' ' ' | awk '{print $1}')
local icon1=$2
local icon2=$3
local icon3=$4
local icon4=$5
if [ "$val" -le 15 ]; then
echo $icon1
elif [ "$val" -le 30 ]; then
echo $icon2
elif [ "$val" -le 60 ]; then
echo $icon3
else
echo $icon4
fi
}
is_muted () {
pactl get-sink-mute $SINK | awk '{print $2}'
}
get_percentage () {
if [[ $(is_muted) == 'yes' ]]; then
echo 0%
else
vol=$(pactl get-sink-volume @DEFAULT_SINK@ | grep Volume | awk '{print $5}' | tr % " ")
echo "${vol}%"
fi
}
get_icon () {
local vol=$(get_percentage)
if [[ $vol == "0%" ]]; then
echo " 婢"
else
echo $(percentage "$vol" "" "" "墳" "")
fi
}
get_class () {
local vol=$(get_percentage)
if [[ $vol == "0%" ]]; then
echo "red"
else
echo $(percentage "$vol" "red" "magenta" "yellow" "blue")
fi
}
get_vol () {
echo $(pactl get-sink-volume @DEFAULT_SINK@ | grep Volume | awk '{print $5}' | tr % " ")
}
if [[ $1 == "icon" ]]; then
while true; do
sleep 0.01
get_icon
done
fi
if [[ $1 == "class" ]]; then
get_class
fi
if [[ $1 == "percentage" ]]; then
get_percentage
fi
if [[ $1 == "vol" ]]; then
get_vol
fi
if [[ $1 == "muted" ]]; then
is_muted
fi
if [[ $1 == "toggle-muted" ]]; then
pactl set-sink-mute $SINK toggle
fi
if [[ $1 == "set" ]]; then
val=$(echo $2 | tr '.' ' ' | awk '{print $1}')
if test $val -gt 100; then
val=100
fi
pactl set-sink-volume $SINK $val%
fi

View file

@ -0,0 +1,76 @@
.osk-toggle {
font-size: 28px;
min-height: 40px;
min-width: 50px;
padding: 0px 0px 0px 5px;
}
.tablet-toggle {
font-size: 28px;
min-height: 40px;
min-width: 50px;
padding: 0px 0px 0px 5px;
}
.heart-toggle {
font-size: 28px;
min-height: 40px;
min-width: 50px;
padding: 0px 0px 0px 4px;
}
.notif-panel {
font-size: 20px;
border-radius: 80px;
min-height: 37px;
min-width: 105px;
padding: 1px 0px 1px 5px;
.toggle-on {
border-top-left-radius: 22px;
border-top-right-radius: 22px;
border-bottom-left-radius: 0px;
border-bottom-right-radius: 0px;
border-bottom: 0px solid $bg;
}
}
.filler {
border-left: 2px solid $contrastbg;
border-right: 2px solid $contrastbg;
min-height: 14px;
min-width: 105px;
background-color: $bg;
transition: all 0.5s;
}
.quick-settings-toggle {
font-size: 24px;
min-height: 40px;
min-width: 40px;
padding: 0px 0px 0px 0px;
}
.toggle-off {
background-color: $bg;
color: #CBA6F7;
border-radius: 80px;
border: 2px solid #1b1b2b;
transition: background-color 0.5s ease-in-out,
border 0.5s ease-in-out;
}
.toggle-on {
background-color: $bg;
color: #CBA6F7;
border-radius: 80px;
border: 2px solid $contrastbg;
transition: background-color 0.5s ease-in-out,
border 0.5s ease-in-out;
}
.toggle-on:hover, .toggle-off:hover {
background-color: rgba(127, 132, 156, 0.4);
transition: background-color 0.5s ease-in-out,
border 0.5s ease-in-out;
}

View file

@ -0,0 +1,164 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; On-Screen Keyboard Toggle
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar osk-ts false)
(defvar osk-run "false")
(defwidget osk-toggle []
(eventbox :class "${osk-ts == 'true' ? 'toggle-on' : 'toggle-off'}"
:onclick "$EWW_PATH/run.sh '$HYPR_PATH/osk-toggle.sh toggle' osk-run &"
:cursor "pointer"
:onhover "eww update osk-run=true"
:onhoverlost "eww update osk-run=false"
(box :class "osk-toggle"
:orientation "h"
(label :text " 󰌌 ")
)
)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Tablet Mode Toggle
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar tablet-ts false)
(defvar tablet-run "false")
(defvar turn-tablet-off "$EWW_PATH/run.sh '$HYPR_PATH/laptop-mode.sh' tablet-run &")
(defvar turn-tablet-on "$EWW_PATH/run.sh '$HYPR_PATH/tablet-mode.sh' tablet-run &")
(defwidget tablet-toggle []
(eventbox :class "${tablet-ts == 'true' ? 'toggle-on' : 'toggle-off'}"
:onclick "${tablet-ts == 'true' ? turn-tablet-off : turn-tablet-on}"
:cursor "pointer"
:onhover "eww update tablet-run=true"
:onhoverlost "eww update tablet-run=false"
(box :class "tablet-toggle"
:orientation "h"
(label :text " 󰦧 ")
)
)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Heart Toggle
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar heart-ts "false")
(defvar heart-run "false")
(defwidget heart-toggle []
(eventbox :class "${heart-ts == 'true' ? 'toggle-on' : 'toggle-off'}"
:onclick "$EWW_PATH/run.sh '$EWW_PATH/heart.sh toggle' heart-run &"
:cursor "pointer"
:onhover "eww update heart-run=true"
:onhoverlost "eww update heart-run=false"
(box :class "heart-toggle"
:orientation "h"
(label :text " ${heart_icon} ")
)
)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Left Bar
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defwidget left-bar []
(box :class "transparent"
:space-evenly true
:spacing 12
:orientation "h"
(osk-toggle)
(tablet-toggle)
(heart-toggle)
)
)
(defwindow left-bar
:monitor 0
:stacking "overlay"
:exclusive "ignore"
:geometry (geometry :x "5px"
:y "10px"
:width "0px"
:height "0px"
:anchor "top left"
)
(left-bar)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Quick Settings Toggle
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar qs-run-on "false")
(defwidget quick-settings-toggle []
(eventbox :class "toggle-off"
:onclick "$EWW_PATH/run.sh '$EWW_PATH/qs-toggle.sh on' qs-run-on &"
:cursor "pointer"
:onhover "eww update qs-run-on=true"
:onhoverlost "eww update qs-run-on=false"
(box :class "quick-settings-toggle"
:orientation "h"
(label :text "  ")
)
)
)
(defwindow quick-settings-toggle
:monitor 0
:stacking "overlay"
:exclusive "ignore"
:geometry (geometry :x "5px"
:y "10px"
:width "0px"
:height "0px"
:anchor "top right"
)
(quick-settings-toggle)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Notification Panel Toggle
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar notif-panel-state false)
(defvar notif-run "false")
(defvar turn-notif-on "$EWW_PATH/run.sh '$EWW_PATH/notif-toggle.sh on' notif-run &")
(defvar turn-notif-off "$EWW_PATH/run.sh '$EWW_PATH/notif-toggle.sh off' notif-run &")
(defwidget notif-panel []
(box :orientation "v"
:space-evenly false
:spacing 0
(eventbox :class "${notif-panel-state == 'true' ? 'toggle-on' : 'toggle-off'}"
:onclick "${notif-panel-state == 'true' ? turn-notif-off : turn-notif-on}"
:cursor "pointer"
:onhover "eww update notif-run=true"
:onhoverlost "eww update notif-run=false"
(box :class "notif-panel"
:orientation "v"
(label :text " ${notif_icon} ")
)
)
(revealer :reveal notif-panel-state
:duration anim_duration
:transition "slideup"
:height 0
(box :class "filler"
:height 0
)
)
)
)
(defwindow notif-panel
:monitor 0
:stacking "overlay"
:exclusive "ignore"
:geometry (geometry :x "60px"
:y "10px"
:width "0px"
:height "0px"
:anchor "top right"
)
(notif-panel)
)

33
config/eww/variables.yuck Normal file
View file

@ -0,0 +1,33 @@
; this var starts all scripts needed when eww boots
(deflisten heart_icon "$EWW_PATH/heart.sh startup")
(defvar cancel_touch "false")
(deflisten notif_icon "$EWW_PATH/notif.sh icon")
(deflisten mic_icon "$EWW_PATH/mic.sh icon")
(deflisten network_ssid "zscroll -d 0.7 -l 12 -p '. ' -u true \"$EWW_PATH/network.sh ssid\"")
(deflisten network_icon "$EWW_PATH/network.sh icon")
(defpoll network_radio :interval "1s" "$EWW_PATH/network.sh radio-status")
(deflisten bluetooth_dev "zscroll -d 0.7 -l 12 -p '. ' -u true \"$EWW_PATH/bluetooth.sh device\"")
(deflisten bluetooth_icon "$EWW_PATH/bluetooth.sh icon")
(deflisten volume_icon "$EWW_PATH/volume.sh icon")
(defpoll volume :interval "1s" "$EWW_PATH/volume.sh percentage")
(defpoll volume_value :interval "1s" "$EWW_PATH/volume.sh vol")
(defpoll is_muted :interval "1s" "$EWW_PATH/volume.sh muted")
(deflisten br_icon "$EWW_PATH/brightness.sh icon")
(defpoll br :interval "1s" "$EWW_PATH/brightness.sh br")
(defvar anim_duration "200ms")
(defpoll completeday :interval "1h" "date '+%A, %d %B'")
(defpoll lithour :interval "30m" "date +%H")
(defpoll litmin :interval "30s" "date +%M")
(defpoll calendar_day :interval "10h" "date '+%d'")
(defpoll calendar_month :interval "10h" "date '+%m")
(defpoll calendar_year :interval "10h" "date '+%Y'")
(defpoll date :interval "30s" "date '+%d %b, %I:%M %p'")
(defpoll shortday :interval "1h" "date '+%d %b %y'")
(defpoll weekday :interval "24h" "date +%A")

View file

@ -0,0 +1,4 @@
[main]
modules=/nix/var/nix/profiles/system/sw/lib/gtklock/powerbar-module.so;/nix/var/nix/profiles/system/sw/lib/gtklock/playerctl-module.so
#;/nix/var/nix/profiles/system/sw/lib/gtklock/userinfo-module.so

5
config/gtklock/scripts/blur.sh Executable file
View file

@ -0,0 +1,5 @@
#!/usr/bin/env bash
grim -t jpeg /tmp/image.jpeg
convert /tmp/image.jpeg -blur 0x8 /tmp/image.jpeg

4
config/gtklock/scripts/lock.sh Executable file
View file

@ -0,0 +1,4 @@
#!/usr/bin/env bash
$HYPR_PATH/laptop-mode.sh &
$LOCK_PATH/blur.sh
gtklock

17
config/gtklock/style.css Normal file
View file

@ -0,0 +1,17 @@
@define-color accent rgba(189, 147, 249, 0.8);
@define-color background rgb(40, 42, 54);
window {
background-image: url("/tmp/image.jpeg");
background-size: cover;
background-repeat: no-repeat;
background-position: center;
background-color: rgba(0, 0, 0, 0);
}
#window-box {
padding: 64px;
border: 2px solid @accent;
border-radius: 30px;
background-color: @background;
}

View file

@ -0,0 +1,2 @@
preload = ~/Pictures/BG/bonzai.jpg
wallpaper = eDP-1, ~/Pictures/BG/bonzai.jpg

242
config/hypr/main.conf Normal file
View file

@ -0,0 +1,242 @@
# Plugins
plugin {
touch_gestures {
# default sensitivity is probably too low on tablet screens,
# I recommend turning it up to 4.0
sensitivity = 20.0
}
}
# See https://wiki.hyprland.org/Configuring/Monitors/
monitor=eDP-1,1920x1200@60,0x0,1
exec-once = $HOME/.config/lisgd/config &
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
# Execute your favorite apps at launch
exec-once = bash -c "sleep 3; XDG_DATA_DIRS=$kora nm-applet"
exec-once = bash -c "sleep 4; blueberry-tray"
exec-once = bash -c "sleep 5; nextcloud --background"
exec-once = eww daemon
exec-once = eww open left-bar
exec-once = eww open notif-panel
exec-once = eww open quick-settings-toggle
# sometimes waybar starts after and stops me from pressing eww buttons
exec-once = bash -c "sleep 0.8; eww reload"
exec-once = gnome-keyring-daemon --start --components=secrets
exec-once = squeekboard
exec-once = wofi --show drun
exec-once = hyprpaper
# after boot, there are 2 bars for some reason, so I kill them and rerun the command
exec-once = bash -c "killall -r -0 waybar && killall -r waybar; XDG_DATA_DIRS=$kora waybar"
exec-once = swaync
exec-once = wl-paste --watch cliphist store
# OSD window
exec-once = swayosd-server
# Change HandleLidSwitch to lock in logind.conf
exec-once = swayidle -w lock $LOCK_PATH/lock.sh
# Special window apps
exec-once = thunderbird # Win + T
exec-once = spot # Win + S
# Some default env vars.
env = XCURSOR_SIZE,24
# For all categories, see https://wiki.hyprland.org/Configuring/Variables/
input {
kb_layout = ca
kb_variant = multix
kb_model =
kb_options =
kb_rules =
follow_mouse = 1
touchpad {
natural_scroll = yes
}
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
}
general {
# See https://wiki.hyprland.org/Configuring/Variables/ for more
gaps_in = 5
gaps_out = 5
border_size = 2
col.active_border = rgb(411C6C)
#col.active_border = rgba(33ccffee) rgba(00ff99ee) 45deg
col.inactive_border = rgba(595959aa)
layout = dwindle
}
misc {
disable_hyprland_logo = true
disable_splash_rendering = true
vfr = true
}
decoration {
# See https://wiki.hyprland.org/Configuring/Variables/ for more
rounding = 20
blur {
enabled = true
size = 3
passes = 1
}
drop_shadow = false
#shadow_range = 4
#shadow_render_power = 3
#col.shadow = rgba(1a1a1aee)
}
animations {
enabled = yes
# Some default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
bezier = myBezier, 0.05, 0.9, 0.1, 1.05
animation = windows, 1, 7, myBezier
animation = windowsOut, 1, 7, default, popin 80%
animation = border, 1, 10, default
animation = borderangle, 1, 8, default
animation = fade, 1, 7, default
animation = workspaces, 1, 6, default
}
dwindle {
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
pseudotile = yes # master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
preserve_split = yes # you probably want this
}
master {
# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
new_is_master = true
}
gestures {
# See https://wiki.hyprland.org/Configuring/Variables/ for more
workspace_swipe = yes
workspace_swipe_fingers = 3
workspace_swipe_cancel_ratio = 0.15
#workspace_swipe_forever = yes
}
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
windowrule = noborder,^(wofi)$
windowrule = workspace special:spot,^(dev.alextren.Spot)$
windowrule = workspace special:thunder,^(thunderbird)$
windowrule = float,^(org.kde.polkit-kde-authentication-agent-1)$
windowrule = size 741 288,^(org.kde.polkit-kde-authentication-agent-1)$
windowrule = center,^(org.kde.polkit-kde-authentication-agent-1)$
windowrule = size 741 288,^(org.kde.ksshaskpass)$
windowrule = move cursor -370 -144,^(org.kde.ksshaskpass)$
windowrule = float,^(org.gnome.Calculator)$
windowrule = size 1231 950,title:^(Open Folder)$
windowrule = float,title:^(Open Folder)$
windowrule = size 1231 950,title:^(Open File)$
windowrule = float,title:^(Open File)$
windowrule = float,^(com.nextcloud.desktopclient.nextcloud)$
windowrule = move cursor 0 25,^(com.nextcloud.desktopclient.nextcloud)$
windowrule = size 400 581,^(com.nextcloud.desktopclient.nextcloud)$
windowrule = tile,^(photoshop.exe)$
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
$mainMod = SUPER
bind = SUPER, F, fullscreen
bind = $mainMod, V, exec, cliphist list | wofi --dmenu | cliphist decode | wl-copy
# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more
bind = $mainMod, Q, exec, alacritty
bind = $mainMod, S, togglespecialworkspace, spot
bind = $mainMod, T, togglespecialworkspace, thunder
bind = $mainMod, C, killactive,
bind = $mainMod, L, exec, $LOCK_PATH/lock.sh
bind = $mainMod SHIFT, E, exec, eww open closer && $EWW_PATH/open.sh powermenu
bindn =, Escape, exec, $EWW_PATH/close-opened.sh
bind = $mainMod SHIFT, SPACE, togglefloating,
bind = $mainMod, D, exec, wofi --show drun
bind = $mainMod, P, pseudo, # dwindle
bind = $mainMod, J, togglesplit, # dwindle
# Move focus with mainMod + arrow keys
bind = $mainMod, left, movefocus, l
bind = $mainMod, right, movefocus, r
bind = $mainMod, up, movefocus, u
bind = $mainMod, down, movefocus, d
# Switch workspaces with mainMod + [0-9]
bind = $mainMod, 1, workspace, 1
bind = $mainMod, 2, workspace, 2
bind = $mainMod, 3, workspace, 3
bind = $mainMod, 4, workspace, 4
bind = $mainMod, 5, workspace, 5
bind = $mainMod, 6, workspace, 6
bind = $mainMod, 7, workspace, 7
bind = $mainMod, 8, workspace, 8
bind = $mainMod, 9, workspace, 9
bind = $mainMod, 0, workspace, 10
# Move active window to a workspace with mainMod + SHIFT + [0-9]
bind = $mainMod SHIFT, 1, movetoworkspace, 1
bind = $mainMod SHIFT, 2, movetoworkspace, 2
bind = $mainMod SHIFT, 3, movetoworkspace, 3
bind = $mainMod SHIFT, 4, movetoworkspace, 4
bind = $mainMod SHIFT, 5, movetoworkspace, 5
bind = $mainMod SHIFT, 6, movetoworkspace, 6
bind = $mainMod SHIFT, 7, movetoworkspace, 7
bind = $mainMod SHIFT, 8, movetoworkspace, 8
bind = $mainMod SHIFT, 9, movetoworkspace, 9
bind = $mainMod SHIFT, 0, movetoworkspace, 10
# Scroll through existing workspaces with mainMod + scroll
bind = $mainMod, mouse_down, workspace, e+1
bind = $mainMod, mouse_up, workspace, e-1
# Move/resize windows with mainMod + LMB/RMB and dragging
bindm = $mainMod, mouse:272, movewindow
bindm = $mainMod, mouse:273, resizewindow
# Take a screenshot
bind =, Print, exec, bash -c 'grim -g "$(slurp)" - | swappy -f -'
bind = $mainMod SHIFT, C, exec, wl-color-picker
# Volume control
binde =, XF86AudioRaiseVolume, exec, swayosd-client --output-volume raise
binde =, XF86AudioLowerVolume, exec, swayosd-client --output-volume lower
bind =, XF86AudioMute, exec, swayosd-client --output-volume mute-toggle
bind =, XF86AudioMicMute, exec, swayosd-client --input-volume mute-toggle
bindr = CAPS, Caps_Lock, exec, swayosd-client --caps-lock
# Brightness control
binde =, XF86MonBrightnessUp, exec, swayosd-client --brightness raise
binde =, XF86MonBrightnessDown, exec, swayosd-client --brightness lower

View file

@ -0,0 +1,51 @@
#!/usr/bin/env bash
# This script was forked from https://gitlab.com/snippets/1793649 by Fishonadish
SCREEN="eDP-1"
WAYLANDINPUT=("wacom-hid-52eb-finger"
"wacom-hid-52eb-pen")
function rotate_ms {
if [[ $(hyprctl activewindow | grep Waydroid) == "" ]]; then
case $1 in
"normal")
rotate 0
;;
"right-up")
rotate 3
;;
"bottom-up")
rotate 2
;;
"left-up")
rotate 1
;;
esac
elif [[ $(hyprctl monitors | grep "transform: 0") == "" ]]; then
rotate 0
fi
}
function rotate {
TARGET_ORIENTATION=$1
echo "Rotating to" $TARGET_ORIENTATION
hyprctl keyword monitor $SCREEN,transform,$TARGET_ORIENTATION
for i in "${WAYLANDINPUT[@]}"
do
hyprctl keyword device:"$i":transform $TARGET_ORIENTATION
done
/home/matt/.config/lisgd/config &
}
while IFS='$\n' read -r line; do
rotation="$(echo $line | sed -En "s/^.*orientation changed: (.*)/\1/p")"
[[ ! -z $rotation ]] && rotate_ms $rotation
done < <(stdbuf -oL monitor-sensor)

View file

@ -0,0 +1,10 @@
#!/usr/bin/env bash
gsettings set org.gnome.desktop.a11y.applications screen-keyboard-enabled false
brightnessctl -d tpacpi::kbd_backlight s 2
killall -r autorotate.sh
killall -r evtest
eww update tablet-ts=false

View file

@ -0,0 +1,16 @@
#!/usr/bin/env bash
while true
do
while killall -0 .blueman-manage > /dev/null 2>&1
do
if bluetoothctl show | grep Powered | grep -q yes; then
if [[ $(hyprctl activewindow | grep blueman-manager) == "" && $(hyprctl clients | grep blueman-manager) != "" ]]; then
killall .blueman-manage
break
fi
sleep 0.1
fi
done
sleep 0.1
done

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