Compare commits
No commits in common. "master" and "no-flakes" have entirely different histories.
542 changed files with 8180 additions and 32292 deletions
|
@ -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
5
.gitattributes
vendored
|
@ -1,5 +0,0 @@
|
|||
flake.lock -diff
|
||||
flake.nix -diff
|
||||
**/non-declarative-conf -diff
|
||||
**/package-lock.json -diff
|
||||
**/HomeAssistantGenerated -diff
|
20
.gitignore
vendored
20
.gitignore
vendored
|
@ -1,22 +1,2 @@
|
|||
# Python
|
||||
*.egg-info
|
||||
|
||||
# NPM
|
||||
*node_modules
|
||||
*build/
|
||||
|
||||
# Direnv
|
||||
*.direnv/
|
||||
|
||||
# Generated by nix
|
||||
result*
|
||||
.nixd.json
|
||||
|
||||
## AGS
|
||||
**/vars.ts
|
||||
**/config.js
|
||||
*icons
|
||||
**/types
|
||||
|
||||
# Other
|
||||
*.temp
|
||||
|
|
16
LICENSE.md
16
LICENSE.md
|
@ -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.
|
115
README.md
115
README.md
|
@ -1,111 +1,18 @@
|
|||
# My NixOS configs
|
||||
|
||||
## AGS
|
||||
what is currently not working:
|
||||
|
||||
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/nixosModules/ags)
|
||||
to see my configuration.
|
||||
- plymouth theme has no login prompt
|
||||
- sddm theme flashes white
|
||||
- autosign in to keyring
|
||||
|
||||
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.
|
||||
what i want to do:
|
||||
|
||||
## About
|
||||
- learn flakes
|
||||
- add auto-rotate widget in ags control center
|
||||
- when multiple widgets open, clicking on a background one puts it forward
|
||||
|
||||
### General
|
||||
## Docs
|
||||
|
||||
This repo is the complete configuration of machines I own,
|
||||
running NixOS or Nix. Its structure is based on a flake's
|
||||
[outputs](https://wiki.nixos.org/wiki/Flakes#Output_schema).
|
||||
|
||||
### 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
|
||||
```
|
||||
|
||||
### Flake Outputs
|
||||
|
||||
| Output | Description |
|
||||
| ---------------------------------- | ----------- |
|
||||
| `nixosConfigurations` | [devices](https://git.nelim.org/matt1432/nixos-configs/src/branch/master/devices)' + ISO's configurations |
|
||||
| `nixOnDroidConfigurations.default` | [Nix-On-Droid](https://git.nelim.org/matt1432/nixos-configs/src/branch/master/devices/android)'s configuration |
|
||||
| `packages` | Some custom [packages](https://git.nelim.org/matt1432/nixos-configs/src/branch/master/packages) not available in nixpkgs or modified from it |
|
||||
| `legacyPackages` | Some custom [package scopes](https://git.nelim.org/matt1432/nixos-configs/src/branch/master/legacyPackages) not available in nixpkgs or modified from it |
|
||||
| `apps` | Scripts ran from the flake defined [here](https://git.nelim.org/matt1432/nixos-configs/src/branch/master/apps) |
|
||||
| `homeManagerModules` | [Modules](https://git.nelim.org/matt1432/nixos-configs/src/branch/master/homeManagerModules) made for home-manager |
|
||||
| `homeManagerModules` | [Modules](https://git.nelim.org/matt1432/nixos-configs/src/branch/master/nixosModules) made for NixOS systems |
|
||||
| `formatter` | I format nix code with [alejandra](https://github.com/kamadorueda/alejandra) |
|
||||
| `devShells.default` | A dev shell to build an ISO from the live-image nixosConfiguration |
|
||||
| `devShells.ags` | A dev shell to have a NodeJS env when I enter my AGS's config directory |
|
||||
|
||||
### Flake Inputs
|
||||
|
||||
To allow use of the full nix language for my inputs, I use [genflake](https://github.com/jorsn/flakegen).
|
||||
Therefore, the flake I edit is located at `./outputs.nix`.
|
||||
|
||||
I also prefer using a more descriptive format for my inputs like so:
|
||||
|
||||
```nix
|
||||
nixpkgs = {
|
||||
type = "github";
|
||||
owner = "NixOS";
|
||||
repo = "nixpkgs";
|
||||
|
||||
# Branch name
|
||||
ref = "nixos-unstable";
|
||||
|
||||
# Pin this input to a specific commit
|
||||
rev = "842d9d80cfd4560648c785f8a4e6f3b096790e19";
|
||||
};
|
||||
```
|
||||
|
||||
to make it more clear what is what in the flake URI
|
||||
|
||||
### 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)
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
{
|
||||
runtimeInputs,
|
||||
npmDepsHash,
|
||||
src,
|
||||
lib,
|
||||
buildNpmPackage,
|
||||
makeWrapper,
|
||||
nodejs_latest,
|
||||
jq,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) concatMapStringsSep getBin;
|
||||
|
||||
packageJSON = builtins.fromJSON (builtins.readFile "${src}/package.json");
|
||||
in
|
||||
buildNpmPackage rec {
|
||||
pname = packageJSON.name;
|
||||
inherit (packageJSON) version;
|
||||
|
||||
inherit src runtimeInputs npmDepsHash;
|
||||
|
||||
prePatch = ''
|
||||
mv ./tsconfig.json ./project.json
|
||||
sed 's/^ *\/\/.*//' ${./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: getBin p) runtimeInputs}
|
||||
'';
|
||||
|
||||
nodejs = nodejs_latest;
|
||||
meta.mainProgram = pname;
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
inputs,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (pkgs.lib) getExe listToAttrs nameValuePair;
|
||||
|
||||
buildApp = attrs: (pkgs.callPackage ./buildApp.nix ({} // inputs // attrs));
|
||||
|
||||
mkApp = file: {
|
||||
program = getExe (pkgs.callPackage file ({inherit buildApp;} // inputs));
|
||||
type = "app";
|
||||
};
|
||||
|
||||
mkApps = apps: listToAttrs (map (x: nameValuePair x (mkApp ./${x})) apps);
|
||||
in
|
||||
mkApps [
|
||||
"extract-subs"
|
||||
"update-sources"
|
||||
]
|
|
@ -1,2 +0,0 @@
|
|||
use flake $FLAKE#subtitles-dev
|
||||
npm ci
|
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
buildApp,
|
||||
ffmpeg-full,
|
||||
...
|
||||
}:
|
||||
buildApp {
|
||||
src = ./.;
|
||||
npmDepsHash = "sha256-XflXVdlsTonDHiR70Th/V6KUf4KSvcwnDod2mkz7rHQ=";
|
||||
|
||||
runtimeInputs = [
|
||||
ffmpeg-full
|
||||
];
|
||||
}
|
|
@ -1,454 +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,tsx}'],
|
||||
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',
|
||||
'@stylistic/jsx-indent-props': 'off',
|
||||
'no-use-before-define': 'off',
|
||||
'@typescript-eslint/no-use-before-define': 'error',
|
||||
'@stylistic/indent-binary-ops': 'off',
|
||||
'@stylistic/max-statements-per-line': [
|
||||
'error',
|
||||
{ max: 2 },
|
||||
],
|
||||
|
||||
// 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',
|
||||
],
|
||||
},
|
||||
],
|
||||
'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',
|
||||
{ allowSingleLine: true },
|
||||
],
|
||||
'@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',
|
||||
],
|
||||
},
|
||||
});
|
BIN
apps/extract-subs/package-lock.json
generated
BIN
apps/extract-subs/package-lock.json
generated
Binary file not shown.
|
@ -1,24 +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/js": "9.14.0",
|
||||
"@stylistic/eslint-plugin": "2.10.1",
|
||||
"@types/node": "22.9.0",
|
||||
"esbuild": "0.24.0",
|
||||
"eslint": "9.14.0",
|
||||
"eslint-plugin-jsdoc": "50.5.0",
|
||||
"jiti": "2.4.0",
|
||||
"typescript": "5.6.3",
|
||||
"typescript-eslint": "8.14.0"
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
console.error('Couldn\'t find streams in video file');
|
||||
|
||||
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);
|
||||
}
|
|
@ -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);
|
||||
});
|
||||
});
|
|
@ -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'],
|
||||
]);
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "../tsconfig.json",
|
||||
"includes": [
|
||||
"*.ts",
|
||||
"**/*.ts",
|
||||
"*.js",
|
||||
"**/*.js"
|
||||
]
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
use flake $FLAKE#node
|
||||
npm ci
|
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
buildApp,
|
||||
callPackage,
|
||||
...
|
||||
}:
|
||||
buildApp {
|
||||
src = ./.;
|
||||
npmDepsHash = "sha256-zl/UIwBQqpV89Rvagyq3mQDJxkWM0h1evtKg9TiTdiw=";
|
||||
|
||||
runtimeInputs = [
|
||||
(callPackage ../../nixosModules/docker/updateImage.nix {})
|
||||
];
|
||||
}
|
|
@ -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',
|
||||
],
|
||||
},
|
||||
});
|
BIN
apps/update-sources/package-lock.json
generated
BIN
apps/update-sources/package-lock.json
generated
Binary file not shown.
|
@ -1,20 +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/js": "9.14.0",
|
||||
"@stylistic/eslint-plugin": "2.10.1",
|
||||
"@types/node": "22.9.0",
|
||||
"esbuild": "0.24.0",
|
||||
"eslint": "9.14.0",
|
||||
"eslint-plugin-jsdoc": "50.5.0",
|
||||
"jiti": "2.4.0",
|
||||
"typescript": "5.6.3",
|
||||
"typescript-eslint": "8.14.0"
|
||||
}
|
||||
}
|
|
@ -1,102 +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 { updateCustomPackage, updateVuetorrent } from './misc';
|
||||
|
||||
|
||||
/* Constants */
|
||||
const FLAKE = process.env.FLAKE;
|
||||
|
||||
if (!FLAKE) {
|
||||
console.error('Env var FLAKE not found');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const args = parseArgs();
|
||||
|
||||
if (args['d'] || args['docker']) {
|
||||
console.log(updateDocker());
|
||||
}
|
||||
|
||||
if (args['i'] || args['inputs']) {
|
||||
console.log(updateFlakeInputs());
|
||||
}
|
||||
|
||||
if (args['f'] || args['firefox']) {
|
||||
console.log(updateFirefoxAddons());
|
||||
}
|
||||
|
||||
if (args['v'] || args['vuetorrent']) {
|
||||
console.log(updateVuetorrent());
|
||||
}
|
||||
|
||||
if (args['c'] || args['custom-sidebar']) {
|
||||
console.log(updateCustomPackage('lovelace-components.custom-sidebar'));
|
||||
}
|
||||
|
||||
if (args['s'] || args['some-sass-language-server']) {
|
||||
console.log(updateCustomPackage('some-sass-language-server'));
|
||||
}
|
||||
|
||||
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 vuetorrentOutput = updateVuetorrent();
|
||||
|
||||
console.log(vuetorrentOutput);
|
||||
|
||||
// This doesn't need to be added to commit msgs
|
||||
console.log(updateCustomPackage('lovelace-components.custom-sidebar'));
|
||||
console.log(updateCustomPackage('some-sass-language-server'));
|
||||
|
||||
|
||||
spawnSync('nix-fast-build', ['-f', `${FLAKE}#nixFastChecks`], {
|
||||
shell: true,
|
||||
stdio: [process.stdin, process.stdout, process.stderr],
|
||||
});
|
||||
|
||||
const output = [
|
||||
'chore: update sources\n\n',
|
||||
];
|
||||
|
||||
if (flakeOutput.length > 5) {
|
||||
output.push(`Flake Inputs:\n${flakeOutput}\n\n`);
|
||||
}
|
||||
if (dockerOutput.length > 5) {
|
||||
output.push(`Docker Images:\n${dockerOutput}\n`);
|
||||
}
|
||||
if (firefoxOutput.length > 5) {
|
||||
output.push(`Firefox Addons:\n${firefoxOutput}\n\n`);
|
||||
}
|
||||
if (vuetorrentOutput.length > 5) {
|
||||
output.push(`Misc Sources:\n${vuetorrentOutput}\n`);
|
||||
}
|
||||
|
||||
if (args['f']) {
|
||||
writeFileSync(args['f'] as string, output.join(''));
|
||||
}
|
||||
else {
|
||||
console.log(output.join(''));
|
||||
}
|
||||
}
|
||||
|
||||
spawnSync('alejandra', ['-q', FLAKE], { shell: true });
|
|
@ -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}/devices/nos/modules/jellyfin`) ?? '';
|
||||
updates += updateImages(`${FLAKE}/devices/homie/modules/home-assistant/netdaemon`) ?? '';
|
||||
|
||||
const DIR = `${FLAKE}/devices/nos/modules/docker`;
|
||||
|
||||
readdirSync(DIR, { withFileTypes: true, recursive: true }).forEach((path) => {
|
||||
if (path.name === 'compose.nix') {
|
||||
updates += updateImages(path.parentPath) ?? '';
|
||||
}
|
||||
});
|
||||
|
||||
return updates;
|
||||
};
|
|
@ -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}/legacyPackages/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',
|
||||
'.#legacyPackages.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');
|
||||
};
|
|
@ -1,35 +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((input) => ![
|
||||
'systems',
|
||||
'flake-utils',
|
||||
'flake-parts',
|
||||
'treefmt-nix',
|
||||
'lib-aggregate',
|
||||
'lib-aggregate/nixpkgs-lib',
|
||||
'sops-nix/nixpkgs-stable',
|
||||
].some((inputName) => input.startsWith(` Updated input '${inputName}'`)))
|
||||
.join('\n\n•')
|
||||
// Shorten git revs to help readability
|
||||
.split('\n')
|
||||
.map((l) => l
|
||||
.replace(/.{33}\?narHash=sha256[^']*/, '')
|
||||
.replace(/&rev=(.{7})[^'&]*/, (_, backref) => `&rev=${backref}`))
|
||||
.join('\n');
|
||||
|
||||
return output;
|
||||
};
|
|
@ -1,30 +0,0 @@
|
|||
import { spawnSync } from 'node:child_process';
|
||||
|
||||
|
||||
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;
|
|
@ -1,47 +0,0 @@
|
|||
import { writeFileSync } from 'node:fs';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
|
||||
import { parseFetchurl } 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}/devices/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}` : '';
|
||||
};
|
||||
|
||||
export const updateCustomPackage = (pkg: string) => spawnSync(
|
||||
`nix run ${FLAKE}#${pkg}.update`,
|
||||
[],
|
||||
{ shell: true },
|
||||
).stderr.toString();
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "../tsconfig.json",
|
||||
"includes": [
|
||||
"*.ts",
|
||||
"**/*.ts",
|
||||
"*.js",
|
||||
"**/*.js"
|
||||
]
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
pkgs,
|
||||
self,
|
||||
}: let
|
||||
inherit (pkgs.lib) mapAttrs' nameValuePair removeAttrs removeSuffix;
|
||||
in
|
||||
mapAttrs'
|
||||
(name: app:
|
||||
nameValuePair "app-${name}" (pkgs.symlinkJoin {
|
||||
name = "app-${name}";
|
||||
paths = [(removeSuffix "/bin/${name}" (toString app.program))];
|
||||
}))
|
||||
(removeAttrs self.apps.${pkgs.system} ["genflake"])
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
pkgs,
|
||||
self,
|
||||
}: let
|
||||
apps = import ./apps.nix {inherit pkgs self;};
|
||||
nixosMachines = import ./machines.nix {inherit pkgs self;};
|
||||
in
|
||||
apps // nixosMachines
|
|
@ -1,10 +0,0 @@
|
|||
# CI: https://github.com/Mic92/dotfiles/blob/c2f538934d67417941f83d8bb65b8263c43d32ca/flake.nix#L168
|
||||
{
|
||||
pkgs,
|
||||
self,
|
||||
}: let
|
||||
inherit (pkgs.lib) filterAttrs mapAttrs' nameValuePair;
|
||||
in
|
||||
mapAttrs'
|
||||
(name: config: nameValuePair "nixos-${name}" config.config.system.build.toplevel)
|
||||
((filterAttrs (_: config: config.pkgs.system == pkgs.system)) self.nixosConfigurations)
|
|
@ -1,131 +0,0 @@
|
|||
{
|
||||
config,
|
||||
home-manager,
|
||||
lib,
|
||||
nh,
|
||||
pkgs,
|
||||
self,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
./vars
|
||||
|
||||
./modules
|
||||
./packages.nix
|
||||
self.nixosModules.borgbackup
|
||||
|
||||
home-manager.nixosModules.home-manager
|
||||
];
|
||||
|
||||
boot.tmp.useTmpfs = true;
|
||||
|
||||
systemd.services.nix-daemon = {
|
||||
environment.TMPDIR = "/home/nix-cache";
|
||||
preStart = ''
|
||||
mkdir -p ${config.systemd.services.nix-daemon.environment.TMPDIR}
|
||||
'';
|
||||
};
|
||||
|
||||
nix = {
|
||||
package = pkgs.nixVersions.nix_2_24;
|
||||
|
||||
# Edit nix.conf
|
||||
settings = {
|
||||
# Store
|
||||
keep-outputs = true;
|
||||
keep-derivations = true;
|
||||
auto-optimise-store = true;
|
||||
|
||||
# Commands
|
||||
experimental-features = ["nix-command" "flakes"];
|
||||
http-connections = 0; # unlimited for local cache
|
||||
warn-dirty = false;
|
||||
show-trace = true;
|
||||
allow-import-from-derivation = true;
|
||||
|
||||
# remote building
|
||||
trusted-users = ["matt" "nixremote"];
|
||||
};
|
||||
};
|
||||
|
||||
programs.nh = {
|
||||
enable = true;
|
||||
package = nh.packages.${pkgs.system}.default;
|
||||
|
||||
# weekly cleanup
|
||||
clean = {
|
||||
enable = true;
|
||||
extraArgs = "--keep-since 30d";
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
fwupd.enable = true;
|
||||
|
||||
xserver.xkb = {
|
||||
layout = "ca";
|
||||
variant = "multix";
|
||||
};
|
||||
};
|
||||
|
||||
boot.supportedFilesystems = ["ext4" "xfs" "btrfs" "vfat" "ntfs"];
|
||||
system.fsPackages = builtins.attrValues {
|
||||
inherit
|
||||
(pkgs)
|
||||
btrfs-progs
|
||||
nfs-utils
|
||||
ntfs3g
|
||||
xfsprogs
|
||||
;
|
||||
};
|
||||
|
||||
environment.variables.NPM_CONFIG_GLOBALCONFIG = "/etc/npmrc";
|
||||
environment.etc.npmrc.text = ''
|
||||
fund = false
|
||||
update-notifier = false
|
||||
'';
|
||||
|
||||
environment.systemPackages = builtins.attrValues {
|
||||
# Peripherals
|
||||
inherit
|
||||
(pkgs)
|
||||
hdparm
|
||||
pciutils
|
||||
usbutils
|
||||
rar
|
||||
;
|
||||
};
|
||||
|
||||
home-manager.users = let
|
||||
inherit (lib) mkIf mkOption types;
|
||||
inherit (config.vars) mainUser;
|
||||
|
||||
default = {
|
||||
imports = [
|
||||
# Make the vars be the same on Nix and HM
|
||||
{
|
||||
options.vars = mkOption {
|
||||
type = types.attrs;
|
||||
readOnly = true;
|
||||
default = config.vars;
|
||||
};
|
||||
}
|
||||
|
||||
{
|
||||
programs.bash.sessionVariables = {
|
||||
FLAKE = config.environment.variables.FLAKE;
|
||||
};
|
||||
}
|
||||
|
||||
./home
|
||||
./home/trash-d
|
||||
];
|
||||
|
||||
home.stateVersion = config.system.stateVersion;
|
||||
};
|
||||
in {
|
||||
root = default;
|
||||
greeter = mkIf (config.services.greetd.enable) default;
|
||||
${mainUser} = default;
|
||||
};
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
# Check git status of nix configs
|
||||
fetchNix() {(
|
||||
cd "$FLAKE" || exit 1
|
||||
git fetch --all --quiet
|
||||
GIT=$(git -c color.status=always status |
|
||||
grep -v -e "On branch" \
|
||||
-e "up to date" \
|
||||
-e 'use "git' \
|
||||
-e "nothing to commit")
|
||||
|
||||
CHECK=$(echo "$GIT" | sed '/^$/d')
|
||||
|
||||
if [ "$CHECK" != "" ]; then
|
||||
echo "$GIT"
|
||||
echo
|
||||
fi
|
||||
)}
|
||||
|
||||
# Check for internet
|
||||
if wget -q --spider https://git.nelim.org; then
|
||||
fetchNix
|
||||
else
|
||||
echo "Offline"
|
||||
fi
|
||||
|
||||
# Pokemon Sprite
|
||||
pokemon-colorscripts -r 1-5
|
|
@ -1,31 +0,0 @@
|
|||
function colorgrid() {
|
||||
iter=16
|
||||
while [ $iter -lt 52 ]
|
||||
do
|
||||
second=$[$iter+36]
|
||||
third=$[$second+36]
|
||||
four=$[$third+36]
|
||||
five=$[$four+36]
|
||||
six=$[$five+36]
|
||||
seven=$[$six+36]
|
||||
if [ $seven -gt 250 ];then seven=$[$seven-251]; fi
|
||||
|
||||
echo -en "\033[38;5;$(echo $iter)m█ "
|
||||
printf "%03d" $iter
|
||||
echo -en " \033[38;5;$(echo $second)m█ "
|
||||
printf "%03d" $second
|
||||
echo -en " \033[38;5;$(echo $third)m█ "
|
||||
printf "%03d" $third
|
||||
echo -en " \033[38;5;$(echo $four)m█ "
|
||||
printf "%03d" $four
|
||||
echo -en " \033[38;5;$(echo $five)m█ "
|
||||
printf "%03d" $five
|
||||
echo -en " \033[38;5;$(echo $six)m█ "
|
||||
printf "%03d" $six
|
||||
echo -en " \033[38;5;$(echo $seven)m█ "
|
||||
printf "%03d" $seven
|
||||
|
||||
iter=$[$iter+1]
|
||||
printf '\r\n'
|
||||
done
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
# Modified from https://github.com/dracula/fzf
|
||||
|
||||
export FZF_DEFAULT_OPTS='--color=fg:#f8f8f2,hl:#bd93f9 --color=fg+:#f8f8f2,hl+:#bd93f9 --color=info:#ffb86c,prompt:#50fa7b,pointer:#ff79c6 --color=marker:#ff79c6,spinner:#ffb86c,header:#6272a4'
|
|
@ -1,10 +0,0 @@
|
|||
# Modified from https://github.com/dracula/man-pages
|
||||
|
||||
#man-page colors
|
||||
export LESS_TERMCAP_mb=$'\e[1;31m' # begin bold
|
||||
export LESS_TERMCAP_md=$'\e[1;34m' # begin blink
|
||||
export LESS_TERMCAP_so=$'\e[01;45;37m' # begin reverse video
|
||||
export LESS_TERMCAP_us=$'\e[01;36m' # begin underline
|
||||
export LESS_TERMCAP_me=$'\e[0m' # reset bold/blink
|
||||
export LESS_TERMCAP_se=$'\e[0m' # reset reverse video
|
||||
export LESS_TERMCAP_ue=$'\e[0m' # reset underline
|
|
@ -1,143 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) concatStrings fileContents;
|
||||
inherit (config.vars) promptColors;
|
||||
in {
|
||||
imports = [./programs.nix];
|
||||
|
||||
programs = {
|
||||
starship = {
|
||||
enable = true;
|
||||
enableBashIntegration = true;
|
||||
|
||||
settings = {
|
||||
format = concatStrings [
|
||||
"╭╴"
|
||||
"[](fg:${promptColors.firstColor})"
|
||||
"[ ](bg:${promptColors.firstColor} fg:#090c0c)"
|
||||
"[](bg:${promptColors.secondColor} fg:${promptColors.firstColor})"
|
||||
"$username$hostname"
|
||||
"[](fg:${promptColors.secondColor} bg:${promptColors.thirdColor})"
|
||||
"$directory"
|
||||
"[](fg:${promptColors.thirdColor} bg:${promptColors.fourthColor})"
|
||||
"$git_branch"
|
||||
"[](fg:${promptColors.fourthColor})$shlvl$nix_shell"
|
||||
"\n╰╴$character"
|
||||
];
|
||||
|
||||
username = {
|
||||
show_always = true;
|
||||
style_user = "fg:${promptColors.textColor} bg:${promptColors.secondColor}";
|
||||
style_root = "fg:red bg:${promptColors.secondColor} blink";
|
||||
format = "[ $user]($style)";
|
||||
};
|
||||
|
||||
hostname = {
|
||||
ssh_only = false;
|
||||
style = "fg:${promptColors.textColor} bg:${promptColors.secondColor}";
|
||||
format = "[@$hostname ]($style)";
|
||||
};
|
||||
|
||||
directory = {
|
||||
style = "fg:${promptColors.firstColor} bg:${promptColors.thirdColor}";
|
||||
format = "[ $path ]($style)";
|
||||
truncate_to_repo = false;
|
||||
truncation_length = 0;
|
||||
|
||||
substitutions = {
|
||||
"Documents" = " ";
|
||||
"Downloads" = " ";
|
||||
"Music" = " ";
|
||||
"Pictures" = " ";
|
||||
};
|
||||
};
|
||||
|
||||
git_branch = {
|
||||
style = "fg:${promptColors.secondColor} bg:${promptColors.fourthColor}";
|
||||
symbol = "";
|
||||
format = "[ $symbol $branch ]($style)";
|
||||
};
|
||||
|
||||
shlvl = {
|
||||
disabled = false;
|
||||
repeat = true;
|
||||
symbol = " ";
|
||||
format = "[ $symbol]($style)";
|
||||
threshold = 1;
|
||||
};
|
||||
|
||||
nix_shell = {
|
||||
symbol = "❄️ ";
|
||||
format = "[ $symbol]($style)";
|
||||
};
|
||||
|
||||
character = {
|
||||
success_symbol = "[\\$](bold green)";
|
||||
error_symbol = "[\\$](bold red)";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
bash = {
|
||||
enable = true;
|
||||
enableCompletion = true;
|
||||
|
||||
historyFile = "\$HOME/.cache/.bash_history";
|
||||
historyFileSize = 100000; # default
|
||||
historySize = 10000; # default
|
||||
historyControl = [
|
||||
"erasedups"
|
||||
"ignorespace"
|
||||
];
|
||||
historyIgnore = [
|
||||
"ls"
|
||||
"exit"
|
||||
"logout"
|
||||
];
|
||||
|
||||
shellOptions = [
|
||||
"histappend"
|
||||
"checkwinsize"
|
||||
"extglob"
|
||||
"globstar"
|
||||
"checkjobs"
|
||||
"autocd"
|
||||
"cdspell"
|
||||
"dirspell"
|
||||
"dotglob"
|
||||
];
|
||||
|
||||
shellAliases = {
|
||||
# Add whitespace after, to allow
|
||||
# sudo to inherit all other aliases
|
||||
sudo = "sudo ";
|
||||
|
||||
ls = "ls -lah --color=auto";
|
||||
tree = "tree -a -I node_modules";
|
||||
cp = "cp -r";
|
||||
};
|
||||
|
||||
#profileExtra = ''
|
||||
#'';
|
||||
bashrcExtra =
|
||||
# bash
|
||||
''
|
||||
# Check if shell is interactive
|
||||
[[ $- == *i* ]] || return 0
|
||||
|
||||
${fileContents ./config/dracula/less.sh}
|
||||
${fileContents ./config/dracula/fzf.sh}
|
||||
|
||||
${fileContents ./config/colorgrid.sh}
|
||||
${fileContents ./config/bashrc}
|
||||
'';
|
||||
#initExtra = ''
|
||||
#'';
|
||||
#logoutExtra = ''
|
||||
#'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
{
|
||||
pkgs,
|
||||
config,
|
||||
self,
|
||||
...
|
||||
}: {
|
||||
programs = {
|
||||
fzf = {
|
||||
enable = true;
|
||||
enableBashIntegration = true;
|
||||
};
|
||||
|
||||
bash = {
|
||||
sessionVariables = {
|
||||
inherit (config.home.sessionVariables) RIPGREP_CONFIG_PATH;
|
||||
};
|
||||
|
||||
shellAliases = {
|
||||
rg = "rga";
|
||||
cat = "bat ";
|
||||
man = "BAT_THEME='default' batman ";
|
||||
};
|
||||
};
|
||||
|
||||
ripgrep = {
|
||||
enable = true;
|
||||
package = pkgs.ripgrep-all;
|
||||
|
||||
arguments = [
|
||||
"--max-columns=150"
|
||||
"--max-columns-preview"
|
||||
"--hidden"
|
||||
"--glob=!.git/*"
|
||||
"--smart-case"
|
||||
"--sort"
|
||||
"path"
|
||||
];
|
||||
};
|
||||
|
||||
jq.enable = true;
|
||||
htop.enable = true;
|
||||
|
||||
bat = {
|
||||
enable = true;
|
||||
|
||||
config.theme = "dracula-bat";
|
||||
themes.dracula-bat.src = self.legacyPackages.${pkgs.system}.dracula.bat;
|
||||
|
||||
extraPackages = builtins.attrValues {
|
||||
inherit (pkgs.bat-extras) batman;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
{...}: {
|
||||
imports = [
|
||||
./bash
|
||||
./direnv
|
||||
./git
|
||||
./neovim
|
||||
./nix-index
|
||||
./tmux
|
||||
];
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
{pkgs, ...}: {
|
||||
programs.direnv = {
|
||||
enable = true;
|
||||
enableBashIntegration = true;
|
||||
|
||||
nix-direnv = {
|
||||
enable = true;
|
||||
package = pkgs.nix-direnv;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
{
|
||||
pkgs,
|
||||
self,
|
||||
...
|
||||
}: let
|
||||
mkRemoteConf = remote: email: name: {
|
||||
condition = "hasconfig:remote.*.url:${remote}:*/**";
|
||||
contents.user = {inherit email name;};
|
||||
};
|
||||
mkDefaultRemote = remote: mkRemoteConf remote "matt@nelim.org" "matt1432";
|
||||
in {
|
||||
programs = {
|
||||
git = {
|
||||
enable = true;
|
||||
package = pkgs.gitFull;
|
||||
|
||||
lfs.enable = true;
|
||||
|
||||
includes = [
|
||||
{path = toString self.legacyPackages.${pkgs.system}.dracula.git;}
|
||||
|
||||
(mkDefaultRemote "https://github.com")
|
||||
(mkDefaultRemote "git@github.com")
|
||||
(mkDefaultRemote "git@git.nelim.org")
|
||||
|
||||
(mkRemoteConf "git@gitlab.info.uqam.ca" "gj591944@ens.uqam.ca" "Mathis Hurtubise")
|
||||
];
|
||||
|
||||
delta = {
|
||||
enable = true;
|
||||
options = {
|
||||
side-by-side = true;
|
||||
line-numbers-zero-style = "#E6EDF3";
|
||||
};
|
||||
};
|
||||
|
||||
extraConfig = {
|
||||
diff.sopsdiffer.textconv = "sops --config /dev/null -d";
|
||||
|
||||
# https://github.com/dandavison/delta/issues/630#issuecomment-860046929
|
||||
pager = let
|
||||
cmd = "LESS='LRc --mouse' ${pkgs.delta}/bin/delta";
|
||||
in {
|
||||
diff = cmd;
|
||||
show = cmd;
|
||||
stash = cmd;
|
||||
log = cmd;
|
||||
reflog = cmd;
|
||||
};
|
||||
|
||||
sendemail = {
|
||||
smtpserver = "127.0.0.1";
|
||||
smtpuser = "matt@nelim.org";
|
||||
smtpencryption = "tls";
|
||||
smtpserverport = 1025;
|
||||
smtpsslcertpath = "";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
home.packages = [
|
||||
(pkgs.writeShellApplication {
|
||||
name = "chore";
|
||||
runtimeInputs = [pkgs.git];
|
||||
|
||||
text = ''
|
||||
DIR=''${1:-"$FLAKE"}
|
||||
|
||||
cd "$DIR" || exit 1
|
||||
|
||||
git add flake.lock
|
||||
git commit -m 'chore: update flake.lock'
|
||||
git push
|
||||
'';
|
||||
})
|
||||
];
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
# see https://github.com/CppCXY/EmmyLuaCodeStyle
|
||||
[*.lua]
|
||||
# [basic]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
quote_style = single
|
||||
|
||||
max_line_length = 120
|
||||
end_of_line = lf
|
||||
|
||||
table_separator_style = comma
|
||||
trailing_table_separator = smart
|
||||
|
||||
call_arg_parentheses = keep
|
||||
|
||||
# [space]
|
||||
space_around_table_field_list = true
|
||||
space_before_attribute = true
|
||||
space_before_function_open_parenthesis = false
|
||||
space_before_function_call_open_parenthesis = false
|
||||
space_before_closure_open_parenthesis = false
|
||||
space_before_function_call_single_arg = false
|
||||
space_before_open_square_bracket = false
|
||||
space_inside_function_call_parentheses = false
|
||||
space_inside_function_param_list_parentheses = false
|
||||
space_inside_square_brackets = false
|
||||
|
||||
# like t[#t+1] = 1
|
||||
space_around_table_append_operator = false
|
||||
ignore_spaces_inside_function_call = false
|
||||
|
||||
# detail number or 'keep'
|
||||
space_before_inline_comment = 1
|
||||
|
||||
# convert '---' to '--- ' or '--' to '-- '
|
||||
space_after_comment_dash = false
|
||||
|
||||
# [operator space]
|
||||
space_around_math_operator = true
|
||||
space_around_math_operator.exponent = false
|
||||
space_around_concat_operator = true
|
||||
space_around_logical_operator = true
|
||||
space_around_assign_operator = true
|
||||
|
||||
space_after_comma = true
|
||||
space_after_comma_in_for_statement = true
|
||||
|
||||
# [align]
|
||||
align_call_args = false
|
||||
align_function_params = true
|
||||
align_continuous_assign_statement = true
|
||||
align_continuous_rect_table_field = true
|
||||
align_continuous_line_space = 2
|
||||
align_if_branch = false
|
||||
|
||||
# option none / always / contain_curly/
|
||||
align_array_table = true
|
||||
|
||||
align_continuous_similar_call_args = false
|
||||
|
||||
align_continuous_inline_comment = true
|
||||
# option none / always / only_call_stmt
|
||||
align_chain_expr = none
|
||||
|
||||
# [indent]
|
||||
never_indent_before_if_condition = false
|
||||
never_indent_comment_on_if_branch = false
|
||||
keep_indents_on_empty_lines = false
|
||||
allow_non_indented_comments = false
|
||||
|
||||
# [line space]
|
||||
|
||||
# The following configuration supports four expressions
|
||||
# keep
|
||||
# fixed(n)
|
||||
# min(n)
|
||||
# max(n)
|
||||
# for eg. min(2)
|
||||
|
||||
line_space_after_if_statement = keep
|
||||
|
||||
line_space_after_do_statement = keep
|
||||
|
||||
line_space_after_while_statement = keep
|
||||
|
||||
line_space_after_repeat_statement = keep
|
||||
|
||||
line_space_after_for_statement = keep
|
||||
|
||||
line_space_after_local_or_assign_statement = keep
|
||||
|
||||
line_space_after_function_statement = fixed(2)
|
||||
|
||||
line_space_after_expression_statement = keep
|
||||
|
||||
line_space_after_comment = keep
|
||||
|
||||
line_space_around_block = fixed(1)
|
||||
|
||||
# [line break]
|
||||
break_all_list_when_line_exceed = false
|
||||
auto_collapse_lines = false
|
||||
break_before_braces = false
|
||||
|
||||
# [preference]
|
||||
ignore_space_after_colon = false
|
||||
end_statement_with_semicolon = always
|
|
@ -1,116 +0,0 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
./git.nix
|
||||
./langs
|
||||
./theme.nix
|
||||
./treesitter.nix
|
||||
];
|
||||
|
||||
programs = {
|
||||
neovim = {
|
||||
enable = true;
|
||||
|
||||
extraLuaConfig =
|
||||
# lua
|
||||
''
|
||||
-- by default, the indent is 2 spaces.
|
||||
vim.opt.smartindent = true;
|
||||
vim.opt.expandtab = true;
|
||||
vim.opt.shiftwidth = 2;
|
||||
vim.opt.softtabstop = 2;
|
||||
vim.opt.tabstop = 2;
|
||||
|
||||
vim.opt.number = true;
|
||||
vim.opt.relativenumber = true;
|
||||
|
||||
vim.opt.undofile = true;
|
||||
vim.opt.undodir = '${config.xdg.cacheHome}/nvim/';
|
||||
|
||||
-- Always show the signcolumn, otherwise it would shift
|
||||
-- the text each time diagnostics appear/become resolved
|
||||
vim.opt.signcolumn = 'yes';
|
||||
|
||||
-- remove highlight on words
|
||||
vim.keymap.set('n', '<esc>', ':noh<cr><esc>', {
|
||||
noremap = true,
|
||||
silent = true,
|
||||
});
|
||||
|
||||
-- Get rid of deprecated messages
|
||||
vim.tbl_add_reverse_lookup = function(tbl)
|
||||
for k, v in pairs(tbl) do
|
||||
tbl[v] = k;
|
||||
end
|
||||
end;
|
||||
vim.tbl_islist = function(tbl)
|
||||
return vim.islist(tbl);
|
||||
end;
|
||||
vim.diagnostic.is_disabled = function()
|
||||
return not vim.diagnostic.is_enabled();
|
||||
end;
|
||||
vim.lsp.buf_get_clients = function()
|
||||
return vim.lsp.get_clients();
|
||||
end;
|
||||
vim.lsp.get_active_clients = function()
|
||||
return vim.lsp.get_clients();
|
||||
end;
|
||||
'';
|
||||
|
||||
plugins = [
|
||||
pkgs.vimPlugins.fzfWrapper
|
||||
pkgs.vimPlugins.fzf-vim
|
||||
|
||||
{
|
||||
plugin = pkgs.vimPlugins.todo-comments-nvim;
|
||||
type = "lua";
|
||||
config =
|
||||
# lua
|
||||
''
|
||||
require('todo-comments').setup();
|
||||
'';
|
||||
}
|
||||
{
|
||||
plugin = pkgs.vimPlugins.mini-nvim;
|
||||
type = "lua";
|
||||
config =
|
||||
# lua
|
||||
''
|
||||
-- TODO: see how this works
|
||||
local ts_input = require('mini.surround').gen_spec.input.treesitter;
|
||||
|
||||
require('mini.surround').setup({
|
||||
custom_surroundings = {
|
||||
-- Use tree-sitter to search for function call
|
||||
f = {
|
||||
input = ts_input({
|
||||
outer = '@call.outer',
|
||||
inner = '@call.inner',
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
'';
|
||||
}
|
||||
|
||||
{
|
||||
plugin = pkgs.vimPlugins.nvim-config-local;
|
||||
type = "lua";
|
||||
config =
|
||||
# lua
|
||||
''
|
||||
require('config-local').setup({
|
||||
config_files = { '.nvim.lua', '.nvimrc', '.exrc' },
|
||||
|
||||
-- Where the plugin keeps files data
|
||||
hashfile = '${config.xdg.cacheHome}/nvim/config-local',
|
||||
});
|
||||
'';
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
{pkgs, ...}: {
|
||||
programs = {
|
||||
neovim = {
|
||||
plugins = [
|
||||
pkgs.vimPlugins.fugitive
|
||||
|
||||
{
|
||||
plugin = pkgs.vimPlugins.gitsigns-nvim;
|
||||
type = "lua";
|
||||
config =
|
||||
# lua
|
||||
''
|
||||
local gitsigns = require("gitsigns");
|
||||
|
||||
local function visual_stage()
|
||||
local first_line = vim.fn.line('v');
|
||||
local last_line = vim.fn.getpos('.')[2];
|
||||
gitsigns.stage_hunk({ first_line, last_line });
|
||||
end
|
||||
|
||||
vim.keymap.set("v", "gs", function()
|
||||
visual_stage()
|
||||
end);
|
||||
|
||||
gitsigns.setup();
|
||||
'';
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) getExe mkIf;
|
||||
inherit (config.vars) neovimIde;
|
||||
in {
|
||||
programs = {
|
||||
# I love doing typos
|
||||
bash.shellAliases = {
|
||||
nivm = "nvim";
|
||||
nivim = "nvim";
|
||||
};
|
||||
|
||||
neovim = {
|
||||
defaultEditor = true;
|
||||
viAlias = true;
|
||||
vimAlias = true;
|
||||
|
||||
extraPackages = mkIf neovimIde [
|
||||
pkgs.nodePackages.bash-language-server
|
||||
pkgs.shellcheck
|
||||
];
|
||||
|
||||
extraLuaConfig =
|
||||
mkIf neovimIde
|
||||
# lua
|
||||
''
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = 'sh',
|
||||
command = 'setlocal ts=4 sw=4 sts=0 expandtab',
|
||||
});
|
||||
|
||||
require('lspconfig').bashls.setup({
|
||||
capabilities = require('cmp_nvim_lsp').default_capabilities(),
|
||||
|
||||
settings = {
|
||||
bashIde = {
|
||||
shellcheckPath = '${getExe pkgs.shellcheck}',
|
||||
},
|
||||
},
|
||||
});
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
inherit (config.vars) neovimIde;
|
||||
in
|
||||
mkIf neovimIde {
|
||||
programs = {
|
||||
neovim = {
|
||||
extraPackages = builtins.attrValues {
|
||||
inherit
|
||||
(pkgs)
|
||||
gcc
|
||||
clang-tools
|
||||
cmake-language-server
|
||||
;
|
||||
};
|
||||
|
||||
extraLuaConfig =
|
||||
# lua
|
||||
''
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = { 'cpp' , 'c'},
|
||||
command = 'setlocal ts=4 sw=4 sts=0 expandtab',
|
||||
});
|
||||
|
||||
local lsp = require('lspconfig');
|
||||
|
||||
lsp.cmake.setup({
|
||||
capabilities = require('cmp_nvim_lsp').default_capabilities(),
|
||||
});
|
||||
|
||||
lsp.clangd.setup({
|
||||
capabilities = require('cmp_nvim_lsp').default_capabilities(),
|
||||
|
||||
handlers = require('lsp-status').extensions.clangd.setup(),
|
||||
on_attach = function(_, bufnr)
|
||||
require("clangd_extensions.inlay_hints").setup_autocmd()
|
||||
require("clangd_extensions.inlay_hints").set_inlay_hints()
|
||||
end,
|
||||
});
|
||||
'';
|
||||
|
||||
plugins = builtins.attrValues {
|
||||
inherit (pkgs.vimPlugins) clangd_extensions-nvim;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
inherit (config.vars) neovimIde;
|
||||
in
|
||||
mkIf neovimIde {
|
||||
programs = {
|
||||
neovim = {
|
||||
extraPackages = builtins.attrValues {
|
||||
inherit
|
||||
(pkgs)
|
||||
omnisharp-roslyn
|
||||
;
|
||||
};
|
||||
|
||||
extraLuaConfig =
|
||||
# lua
|
||||
''
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = { 'cs' },
|
||||
command = 'setlocal ts=4 sw=4 sts=0 expandtab',
|
||||
});
|
||||
|
||||
local omnisharp_extended = require('omnisharp_extended');
|
||||
|
||||
require('lspconfig').omnisharp.setup({
|
||||
cmd = { "dotnet", "${pkgs.omnisharp-roslyn}/lib/omnisharp-roslyn/OmniSharp.dll" },
|
||||
|
||||
handlers = {
|
||||
["textDocument/definition"] = omnisharp_extended.definition_handler,
|
||||
["textDocument/typeDefinition"] = omnisharp_extended.type_definition_handler,
|
||||
["textDocument/references"] = omnisharp_extended.references_handler,
|
||||
["textDocument/implementation"] = omnisharp_extended.implementation_handler,
|
||||
},
|
||||
|
||||
settings = {
|
||||
FormattingOptions = {
|
||||
EnableEditorConfigSupport = true,
|
||||
OrganizeImports = true,
|
||||
},
|
||||
MsBuild = {
|
||||
LoadProjectsOnDemand = false,
|
||||
},
|
||||
RoslynExtensionsOptions = {
|
||||
EnableAnalyzersSupport = true,
|
||||
EnableDecompilationSupport = true,
|
||||
EnableImportCompletion = true,
|
||||
AnalyzeOpenDocumentsOnly = false,
|
||||
},
|
||||
Sdk = {
|
||||
IncludePrereleases = true,
|
||||
},
|
||||
},
|
||||
});
|
||||
'';
|
||||
|
||||
plugins = builtins.attrValues {
|
||||
inherit (pkgs.vimPlugins) omnisharp-extended-lsp-nvim;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) fileContents mkBefore mkIf;
|
||||
inherit (config.vars) neovimIde;
|
||||
in {
|
||||
imports = [
|
||||
./bash.nix
|
||||
./clang.nix
|
||||
./csharp.nix
|
||||
./hyprlang.nix
|
||||
./java.nix
|
||||
./json.nix
|
||||
./lua.nix
|
||||
./markdown.nix
|
||||
./nix.nix
|
||||
./python.nix
|
||||
./rust.nix
|
||||
./web.nix
|
||||
];
|
||||
|
||||
programs = mkIf neovimIde {
|
||||
neovim = {
|
||||
extraLuaConfig =
|
||||
mkBefore
|
||||
# lua
|
||||
''
|
||||
-- Start completion / snippet stuff
|
||||
vim.g.coq_settings = {
|
||||
auto_start = 'shut-up',
|
||||
keymap = {
|
||||
recommended = false,
|
||||
},
|
||||
-- https://github.com/NixOS/nixpkgs/issues/168928#issuecomment-1109581739
|
||||
xdg = true,
|
||||
};
|
||||
|
||||
-- Add formatting cmd
|
||||
vim.api.nvim_create_user_command(
|
||||
'Format',
|
||||
function()
|
||||
vim.lsp.buf.format({ async = true });
|
||||
end,
|
||||
{}
|
||||
);
|
||||
|
||||
-- LSP-Status setup
|
||||
local lsp_status = require('lsp-status');
|
||||
lsp_status.register_progress();
|
||||
|
||||
-- Remove LSP highlighting to use Treesitter
|
||||
vim.api.nvim_create_autocmd('LspAttach', {
|
||||
callback = function(args)
|
||||
local client = vim.lsp.get_client_by_id(args.data.client_id);
|
||||
client.server_capabilities.semanticTokensProvider = nil;
|
||||
lsp_status.on_attach(client);
|
||||
end,
|
||||
});
|
||||
|
||||
-- Disable virtual_text since it's redundant due to lsp_lines.
|
||||
vim.diagnostic.config({
|
||||
virtual_text = false,
|
||||
});
|
||||
|
||||
require('lsp_lines').setup();
|
||||
'';
|
||||
|
||||
plugins =
|
||||
(builtins.attrValues {
|
||||
inherit
|
||||
(pkgs.vimPlugins)
|
||||
nvim-lspconfig
|
||||
lsp-status-nvim
|
||||
lsp_lines-nvim
|
||||
cmp-buffer
|
||||
cmp-nvim-lsp
|
||||
cmp-path
|
||||
cmp-spell
|
||||
vim-vsnip
|
||||
;
|
||||
})
|
||||
++ [
|
||||
{
|
||||
plugin = pkgs.vimPlugins.nvim-cmp;
|
||||
type = "lua";
|
||||
config = fileContents ../plugins/cmp.lua;
|
||||
}
|
||||
|
||||
{
|
||||
plugin = pkgs.vimPlugins.nvim-autopairs;
|
||||
type = "lua";
|
||||
config =
|
||||
# lua
|
||||
''
|
||||
require('nvim-autopairs').setup({});
|
||||
'';
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
inherit (config.vars) neovimIde;
|
||||
in
|
||||
mkIf neovimIde {
|
||||
programs = {
|
||||
neovim = {
|
||||
extraLuaConfig =
|
||||
# lua
|
||||
''
|
||||
vim.filetype.add({
|
||||
pattern = { ['.*/hypr/.*%.conf'] = 'hyprlang' },
|
||||
});
|
||||
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = 'hyprlang',
|
||||
command = 'setlocal ts=4 sw=4 sts=0 expandtab',
|
||||
});
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) getExe mkIf;
|
||||
inherit (config.vars) neovimIde;
|
||||
|
||||
javaSdk = pkgs.temurin-bin-17;
|
||||
javaPkgs = builtins.attrValues {inherit (pkgs) gradle maven;};
|
||||
in
|
||||
mkIf neovimIde {
|
||||
home.packages = javaPkgs;
|
||||
|
||||
xdg.dataFile.".gradle/gradle.properties".text = ''
|
||||
org.gradle.java.home = ${javaSdk}
|
||||
'';
|
||||
|
||||
programs = {
|
||||
java = {
|
||||
enable = true;
|
||||
package = javaSdk;
|
||||
};
|
||||
|
||||
neovim = {
|
||||
extraPackages = javaPkgs;
|
||||
|
||||
extraLuaConfig =
|
||||
# lua
|
||||
''
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = 'java',
|
||||
command = 'setlocal ts=4 sw=4 sts=0 expandtab',
|
||||
});
|
||||
'';
|
||||
|
||||
plugins = [
|
||||
{
|
||||
# TOOD: setup debugger https://github.com/mfussenegger/nvim-jdtls#debugger-via-nvim-dap
|
||||
plugin = pkgs.vimPlugins.nvim-jdtls;
|
||||
type = "lua";
|
||||
config =
|
||||
# lua
|
||||
''
|
||||
--
|
||||
local startJdtls = function()
|
||||
local config = {
|
||||
capabilities = require('cmp_nvim_lsp').default_capabilities(),
|
||||
|
||||
cmd = { '${getExe pkgs.jdt-language-server}' },
|
||||
root_dir = vim.fs.dirname(vim.fs.find(
|
||||
{ 'gradlew', '.git', 'mvnw', 'pom.xml' },
|
||||
{ upward = true }
|
||||
)[1]),
|
||||
|
||||
settings = {
|
||||
java = {
|
||||
configuration = {
|
||||
runtimes = {
|
||||
{
|
||||
name = 'JavaSE-17',
|
||||
path = '${javaSdk}',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
require('jdtls').start_or_attach(config);
|
||||
end
|
||||
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = 'java',
|
||||
callback = startJdtls,
|
||||
});
|
||||
'';
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
inherit (config.vars) neovimIde;
|
||||
in
|
||||
mkIf neovimIde {
|
||||
programs = {
|
||||
neovim = {
|
||||
extraPackages = builtins.attrValues {
|
||||
inherit
|
||||
(pkgs)
|
||||
vscode-langservers-extracted
|
||||
yaml-language-server
|
||||
;
|
||||
};
|
||||
|
||||
extraLuaConfig =
|
||||
# lua
|
||||
''
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = 'yaml',
|
||||
command = 'setlocal ts=4 sw=4 sts=0 expandtab',
|
||||
});
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = 'json',
|
||||
command = 'setlocal ts=4 sw=4 sts=0 expandtab',
|
||||
});
|
||||
|
||||
local lsp = require('lspconfig');
|
||||
|
||||
lsp.jsonls.setup({
|
||||
capabilities = require('cmp_nvim_lsp').default_capabilities(),
|
||||
});
|
||||
|
||||
lsp.yamlls.setup({
|
||||
capabilities = require('cmp_nvim_lsp').default_capabilities(),
|
||||
|
||||
settings = {
|
||||
yaml = {
|
||||
schemas = {
|
||||
[
|
||||
"https://json.schemastore.org/github-workflow.json"
|
||||
] = "/.github/workflows/*",
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
inherit (config.vars) neovimIde;
|
||||
|
||||
flakeEnv = config.programs.bash.sessionVariables.FLAKE;
|
||||
in
|
||||
mkIf neovimIde {
|
||||
programs = {
|
||||
neovim = {
|
||||
extraPackages = builtins.attrValues {
|
||||
inherit (pkgs) lua-language-server;
|
||||
};
|
||||
|
||||
plugins = [
|
||||
{
|
||||
plugin = pkgs.vimPlugins.neodev-nvim;
|
||||
type = "lua";
|
||||
config =
|
||||
# lua
|
||||
''
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = 'lua',
|
||||
command = 'setlocal ts=4 sw=4 sts=0 expandtab',
|
||||
});
|
||||
|
||||
-- IMPORTANT: make sure to setup neodev BEFORE lspconfig
|
||||
require("neodev").setup({
|
||||
override = function(root_dir, library)
|
||||
if root_dir:find('${flakeEnv}', 1, true) == 1 then
|
||||
library.enabled = true
|
||||
library.plugins = true
|
||||
end
|
||||
end,
|
||||
});
|
||||
|
||||
require('lspconfig').lua_ls.setup({
|
||||
capabilities = require('cmp_nvim_lsp').default_capabilities(),
|
||||
});
|
||||
'';
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,128 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
self,
|
||||
vimplugin-easytables-src,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
inherit (config.vars) neovimIde;
|
||||
|
||||
inherit (import "${self}/lib" {inherit pkgs;}) buildPlugin;
|
||||
in
|
||||
mkIf neovimIde {
|
||||
programs = {
|
||||
neovim = {
|
||||
extraPackages = builtins.attrValues {
|
||||
inherit
|
||||
(pkgs)
|
||||
pandoc
|
||||
texlab
|
||||
texliveFull
|
||||
rubber
|
||||
;
|
||||
};
|
||||
|
||||
extraLuaConfig =
|
||||
# lua
|
||||
''
|
||||
local lsp = require('lspconfig');
|
||||
|
||||
lsp.texlab.setup({
|
||||
capabilities = require('cmp_nvim_lsp').default_capabilities(),
|
||||
|
||||
settings = {
|
||||
texlab = {
|
||||
formatterLineLength = 100,
|
||||
latexFormatter = 'latexindent',
|
||||
latexindent = {
|
||||
modifyLineBreaks = false,
|
||||
["local"] = '.indentconfig.yaml';
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
'';
|
||||
|
||||
plugins = [
|
||||
{
|
||||
plugin = buildPlugin "easytables-nvim" vimplugin-easytables-src;
|
||||
type = "lua";
|
||||
config =
|
||||
# lua
|
||||
''
|
||||
require('easytables').setup();
|
||||
'';
|
||||
}
|
||||
|
||||
{
|
||||
plugin = pkgs.vimPlugins.knap;
|
||||
type = "lua";
|
||||
config =
|
||||
# lua
|
||||
''
|
||||
--
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = 'tex',
|
||||
command = 'setlocal ts=4 sw=4 sts=0 expandtab',
|
||||
});
|
||||
|
||||
vim.g.knap_settings = {
|
||||
-- HTML
|
||||
htmloutputext = 'html',
|
||||
htmltohtml = 'none',
|
||||
htmltohtmlviewerlaunch = "",
|
||||
htmltohtmlviewerrefresh = 'none',
|
||||
|
||||
-- Markdown
|
||||
mdoutputext = 'html',
|
||||
markdownoutputext = 'html',
|
||||
|
||||
-- Markdown to PDF
|
||||
mdtopdf = 'pandoc %docroot% -o /tmp/%outputfile%',
|
||||
markdowntopdf = 'pandoc %docroot% -o /tmp/%outputfile%',
|
||||
mdtopdfviewerlaunch = 'sioyek /tmp/%outputfile%',
|
||||
markdowntopdfviewerlaunch = 'sioyek /tmp/%outputfile%',
|
||||
mdtopdfviewerrefresh = 'none',
|
||||
markdowntopdfviewerrefresh = "none",
|
||||
|
||||
-- Markdown to HTML
|
||||
mdtohtml = 'pandoc --standalone %docroot% -o /tmp/%outputfile%',
|
||||
markdowntohtml = 'pandoc --standalone %docroot% -o /tmp/%outputfile%',
|
||||
mdtohtmlviewerlaunch = 'firefox -new-window /tmp/%outputfile%',
|
||||
markdowntohtmlviewerlaunch = 'firefox -new-window /tmp/%outputfile%',
|
||||
mdtohtmlviewerrefresh = 'none',
|
||||
markdowntohtmlviewerrefresh = 'none',
|
||||
|
||||
-- LaTeX
|
||||
-- TODO: stop from polluting workspace
|
||||
};
|
||||
|
||||
-- F4 processes the document once, and refreshes the view
|
||||
vim.keymap.set({ 'n', 'v', 'i' }, '<F4>', function()
|
||||
require('knap').process_once();
|
||||
end);
|
||||
|
||||
-- F5 closes the viewer application, and
|
||||
-- allows settings to be reset
|
||||
vim.keymap.set({ 'n', 'v', 'i' }, '<F5>', function()
|
||||
require('knap').close_viewer();
|
||||
end);
|
||||
|
||||
-- F6 toggles the auto-processing on and off
|
||||
vim.keymap.set({ 'n', 'v', 'i' }, '<F6>', function()
|
||||
require('knap').toggle_autopreviewing();
|
||||
end);
|
||||
|
||||
-- F7 invokes a SyncTeX forward search, or similar,
|
||||
-- where appropriate
|
||||
vim.keymap.set({ 'n', 'v', 'i' }, '<F7>', function()
|
||||
require('knap').forward_jump();
|
||||
end);
|
||||
'';
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
nixd,
|
||||
self,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) getExe hasPrefix mkIf removePrefix;
|
||||
inherit (config.vars) hostName mainUser neovimIde;
|
||||
|
||||
defaultFormatter = self.formatter.${pkgs.system};
|
||||
|
||||
nixdPkg = nixd.packages.${pkgs.system}.default;
|
||||
|
||||
flakeEnv = config.programs.bash.sessionVariables.FLAKE;
|
||||
flakeDir = "${removePrefix "/home/${mainUser}/" flakeEnv}";
|
||||
in
|
||||
mkIf neovimIde {
|
||||
assertions = [
|
||||
{
|
||||
assertion =
|
||||
neovimIde
|
||||
&& hasPrefix "/home/${mainUser}/" flakeEnv
|
||||
|| !neovimIde;
|
||||
message = ''
|
||||
Your $FLAKE environment variable needs to point to a directory in
|
||||
the main users' home to use the neovim module.
|
||||
'';
|
||||
}
|
||||
];
|
||||
|
||||
home.packages = [
|
||||
defaultFormatter
|
||||
nixdPkg
|
||||
];
|
||||
|
||||
# nixd by default kinda spams LspLog
|
||||
home.sessionVariables.NIXD_FLAGS = "-log=error";
|
||||
|
||||
xdg.dataFile."${flakeDir}/.nixd.json".text = builtins.toJSON {
|
||||
nixpkgs = {
|
||||
expr = "import (builtins.getFlake \"${flakeDir}\").inputs.nixpkgs {}";
|
||||
};
|
||||
options.nixos = {
|
||||
expr = "(builtins.getFlake \"${flakeDir}\").nixosConfigurations.${hostName}.options";
|
||||
};
|
||||
};
|
||||
|
||||
programs = {
|
||||
neovim = {
|
||||
extraPackages = [
|
||||
nixdPkg
|
||||
];
|
||||
|
||||
extraLuaConfig =
|
||||
# lua
|
||||
''
|
||||
require('lspconfig').nixd.setup({
|
||||
capabilities = require('cmp_nvim_lsp').default_capabilities(),
|
||||
|
||||
filetypes = { 'nix', 'in.nix' },
|
||||
settings = {
|
||||
nixd = {
|
||||
formatting = {
|
||||
-- TODO: Try to find <flake>.formatter
|
||||
command = { '${getExe defaultFormatter}' },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
inherit (config.vars) neovimIde;
|
||||
in
|
||||
mkIf neovimIde {
|
||||
programs = {
|
||||
neovim = {
|
||||
withPython3 = true;
|
||||
|
||||
extraPackages = [
|
||||
pkgs.basedpyright
|
||||
];
|
||||
|
||||
extraLuaConfig =
|
||||
# lua
|
||||
''
|
||||
require('lspconfig').basedpyright.setup({
|
||||
capabilities = require('cmp_nvim_lsp').default_capabilities(),
|
||||
});
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
inherit (config.vars) neovimIde;
|
||||
in
|
||||
mkIf neovimIde {
|
||||
programs = {
|
||||
neovim = {
|
||||
extraPackages = builtins.attrValues {
|
||||
inherit
|
||||
(pkgs)
|
||||
cargo
|
||||
rustc
|
||||
rust-analyzer
|
||||
rustfmt
|
||||
;
|
||||
};
|
||||
|
||||
extraLuaConfig =
|
||||
# lua
|
||||
''
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = { 'rust' },
|
||||
command = 'setlocal ts=4 sw=4 sts=0 expandtab',
|
||||
});
|
||||
|
||||
require('lspconfig').rust_analyzer.setup({
|
||||
capabilities = require('cmp_nvim_lsp').default_capabilities(),
|
||||
});
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,200 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
self,
|
||||
vimplugin-ts-error-translator-src,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
inherit (config.vars) neovimIde;
|
||||
|
||||
inherit (import "${self}/lib" {inherit pkgs;}) buildPlugin;
|
||||
in
|
||||
mkIf neovimIde {
|
||||
programs = {
|
||||
neovim = {
|
||||
withNodeJs = true;
|
||||
|
||||
extraPackages = builtins.attrValues {
|
||||
inherit
|
||||
(pkgs)
|
||||
nodejs_latest
|
||||
vscode-langservers-extracted
|
||||
;
|
||||
|
||||
inherit
|
||||
(pkgs.nodePackages)
|
||||
npm
|
||||
neovim
|
||||
;
|
||||
|
||||
inherit
|
||||
(self.packages.${pkgs.system})
|
||||
some-sass-language-server
|
||||
;
|
||||
};
|
||||
|
||||
extraLuaConfig =
|
||||
# lua
|
||||
''
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = { 'javascript', 'javascriptreact', 'javascript.jsx', 'typescript', 'typescriptreact', 'typescript.tsx', 'css', 'scss' },
|
||||
command = 'setlocal ts=4 sw=4 sts=0 expandtab',
|
||||
});
|
||||
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = 'html',
|
||||
command = 'setlocal ts=4 sw=4 expandtab',
|
||||
});
|
||||
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = 'scss',
|
||||
command = 'setlocal iskeyword+=@-@',
|
||||
});
|
||||
|
||||
local lsp = require('lspconfig');
|
||||
local tsserver = require('typescript-tools');
|
||||
local default_capabilities = require('cmp_nvim_lsp').default_capabilities();
|
||||
|
||||
tsserver.setup({
|
||||
capabilities = default_capabilities,
|
||||
|
||||
handlers = {
|
||||
-- format error code with better error message
|
||||
['textDocument/publishDiagnostics'] = function(err, result, ctx, config)
|
||||
require('ts-error-translator').translate_diagnostics(err, result, ctx, config)
|
||||
vim.lsp.diagnostic.on_publish_diagnostics(err, result, ctx, config)
|
||||
end,
|
||||
},
|
||||
});
|
||||
|
||||
lsp.eslint.setup({
|
||||
capabilities = default_capabilities,
|
||||
|
||||
-- auto-save
|
||||
on_attach = function(client, bufnr)
|
||||
vim.api.nvim_create_autocmd('BufWritePre', {
|
||||
buffer = bufnr,
|
||||
command = 'EslintFixAll',
|
||||
});
|
||||
end,
|
||||
|
||||
settings = {
|
||||
validate = 'on',
|
||||
packageManager = 'npm',
|
||||
useESLintClass = true,
|
||||
useFlatConfig = true,
|
||||
experimental = {
|
||||
useFlatConfig = true,
|
||||
},
|
||||
codeAction = {
|
||||
disableRuleComment = {
|
||||
enable = true,
|
||||
location = 'separateLine'
|
||||
},
|
||||
showDocumentation = {
|
||||
enable = true,
|
||||
},
|
||||
},
|
||||
codeActionOnSave = {
|
||||
mode = 'all',
|
||||
rules = {},
|
||||
},
|
||||
format = true,
|
||||
quiet = false,
|
||||
onIgnoredFiles = 'off',
|
||||
rulesCustomizations = {},
|
||||
run = 'onType',
|
||||
problems = {
|
||||
shortenToSingleLine = false,
|
||||
},
|
||||
nodePath = "",
|
||||
workingDirectory = {
|
||||
mode = 'location',
|
||||
},
|
||||
options = {
|
||||
flags = {'unstable_ts_config'},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
lsp.cssls.setup({
|
||||
capabilities = default_capabilities,
|
||||
|
||||
settings = {
|
||||
css = {
|
||||
validate = false,
|
||||
},
|
||||
less = {
|
||||
validate = false,
|
||||
},
|
||||
scss = {
|
||||
validate = false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
lsp.somesass_ls.setup({
|
||||
capabilities = default_capabilities,
|
||||
});
|
||||
lsp.somesass_ls.manager.config.settings = {
|
||||
somesass = {
|
||||
scss = {
|
||||
completion = {
|
||||
suggestFromUseOnly = true,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
local html_caps = default_capabilities;
|
||||
html_caps.textDocument.completion.completionItem.snippetSupport = true;
|
||||
|
||||
lsp.html.setup({
|
||||
capabilities = html_caps,
|
||||
settings = {
|
||||
configurationSection = { "html", "css", "javascript" },
|
||||
embeddedLanguages = {
|
||||
css = true,
|
||||
javascript = true,
|
||||
},
|
||||
provideFormatter = true,
|
||||
tabSize = 4,
|
||||
insertSpaces = true,
|
||||
indentEmptyLines = false,
|
||||
wrapAttributes = 'auto',
|
||||
wrapAttributesIndentSize = 4,
|
||||
endWithNewline = true,
|
||||
},
|
||||
});
|
||||
'';
|
||||
|
||||
plugins = [
|
||||
pkgs.vimPlugins.typescript-tools-nvim
|
||||
(buildPlugin "ts-error-translator" vimplugin-ts-error-translator-src)
|
||||
|
||||
{
|
||||
plugin = pkgs.vimPlugins.package-info-nvim;
|
||||
type = "lua";
|
||||
config =
|
||||
# lua
|
||||
''
|
||||
local packageInfo = require('package-info');
|
||||
packageInfo.setup({
|
||||
hide_up_to_date = true,
|
||||
package_manager = 'npm',
|
||||
});
|
||||
|
||||
vim.api.nvim_create_autocmd({ 'BufRead', 'BufNewFile' }, {
|
||||
pattern = { 'package.json' },
|
||||
callback = function()
|
||||
packageInfo.show({ force = true });
|
||||
end,
|
||||
});
|
||||
'';
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
local cmp = require('cmp');
|
||||
local cmp_autopairs = require('nvim-autopairs.completion.cmp');
|
||||
|
||||
cmp.event:on(
|
||||
'confirm_done',
|
||||
cmp_autopairs.on_confirm_done()
|
||||
);
|
||||
|
||||
cmp.setup({
|
||||
sources = {
|
||||
{ name = 'nvim_lsp' },
|
||||
{ name = 'buffer' },
|
||||
{ name = 'path' },
|
||||
},
|
||||
|
||||
snippet = {
|
||||
expand = function(args)
|
||||
vim.fn['vsnip#anonymous'](args.body);
|
||||
end,
|
||||
},
|
||||
|
||||
mapping = {
|
||||
-- Confirm selection
|
||||
['<Right>'] = cmp.mapping.confirm({ select = true }),
|
||||
|
||||
-- Next selection
|
||||
['<Down>'] = cmp.mapping(function(fallback)
|
||||
if cmp.visible() then
|
||||
cmp.select_next_item();
|
||||
else
|
||||
fallback();
|
||||
end;
|
||||
end, {
|
||||
'i',
|
||||
's',
|
||||
}),
|
||||
|
||||
-- Previous selection
|
||||
['<Up>'] = cmp.mapping(function(fallback)
|
||||
if cmp.visible() then
|
||||
cmp.select_prev_item();
|
||||
else
|
||||
fallback();
|
||||
end;
|
||||
end, {
|
||||
'i',
|
||||
's',
|
||||
}),
|
||||
},
|
||||
});
|
|
@ -1,443 +0,0 @@
|
|||
-- Modified from https://github.com/lauranaujokat/nvim/blob/4102c789d05667f636107e3dae4ac589053ee88d/lua/setups/heirline.lua#L4
|
||||
|
||||
local conditions = require('heirline.conditions');
|
||||
local utils = require('heirline.utils');
|
||||
|
||||
---@class Palette
|
||||
---@field [string] any
|
||||
local dracula = require('dracula').colors();
|
||||
|
||||
local colors = {
|
||||
bright_bg = dracula.selection,
|
||||
dark_bg = dracula.menu,
|
||||
bright_fg = dracula.fg,
|
||||
red = dracula.red,
|
||||
dark_red = utils.get_highlight('DiffDelete').bg,
|
||||
green = dracula.green,
|
||||
blue = dracula.blue,
|
||||
gray = utils.get_highlight('NonText').fg,
|
||||
orange = utils.get_highlight('Constant').fg,
|
||||
purple = utils.get_highlight('Statement').fg,
|
||||
cyan = dracula.cyan,
|
||||
diag_warn = utils.get_highlight('DiagnosticWarn').fg,
|
||||
diag_error = utils.get_highlight('DiagnosticError').fg,
|
||||
diag_hint = utils.get_highlight('DiagnosticHint').fg,
|
||||
diag_info = utils.get_highlight('DiagnosticInfo').fg,
|
||||
git_del = utils.get_highlight('GitSignsDelete').fg,
|
||||
git_add = utils.get_highlight('GitSignsAdd').fg,
|
||||
git_change = utils.get_highlight('GitSignsChange').fg,
|
||||
};
|
||||
|
||||
require('heirline').load_colors(colors);
|
||||
|
||||
local ViMode = {
|
||||
-- get vim current mode, this information will be required by the provider
|
||||
-- and the highlight functions, so we compute it only once per component
|
||||
-- evaluation and store it as a component attribute
|
||||
init = function(self)
|
||||
self.mode = vim.fn.mode(1);
|
||||
|
||||
-- execute this only once, this is required if you want the ViMode
|
||||
-- component to be updated on operator pending mode
|
||||
if not self.once then
|
||||
vim.api.nvim_create_autocmd('ModeChanged', {
|
||||
pattern = '*:*o',
|
||||
command = 'redrawstatus',
|
||||
});
|
||||
self.once = true;
|
||||
end;
|
||||
end,
|
||||
|
||||
static = {
|
||||
mode_names = {
|
||||
n = 'N',
|
||||
no = 'N?',
|
||||
nov = 'N?',
|
||||
noV = 'N?',
|
||||
['no\22'] = 'N?',
|
||||
niI = 'Ni',
|
||||
niR = 'Nr',
|
||||
niV = 'Nv',
|
||||
nt = 'Nt',
|
||||
v = 'V',
|
||||
vs = 'Vs',
|
||||
V = 'V_',
|
||||
Vs = 'Vs',
|
||||
['\22'] = '^V',
|
||||
['\22s'] = '^V',
|
||||
s = 'S',
|
||||
S = 'S_',
|
||||
['\19'] = '^S',
|
||||
i = 'I',
|
||||
ic = 'Ic',
|
||||
ix = 'Ix',
|
||||
R = 'R',
|
||||
Rc = 'Rc',
|
||||
Rx = 'Rx',
|
||||
Rv = 'Rv',
|
||||
Rvc = 'Rv',
|
||||
Rvx = 'Rv',
|
||||
c = 'C',
|
||||
cv = 'Ex',
|
||||
r = '...',
|
||||
rm = 'M',
|
||||
['r?'] = '?',
|
||||
['!'] = '!',
|
||||
t = 'T',
|
||||
},
|
||||
|
||||
mode_colors = {
|
||||
n = 'red',
|
||||
i = 'green',
|
||||
v = 'cyan',
|
||||
V = 'cyan',
|
||||
['\22'] = 'cyan',
|
||||
c = 'orange',
|
||||
s = 'purple',
|
||||
S = 'purple',
|
||||
['\19'] = 'purple',
|
||||
R = 'orange',
|
||||
r = 'orange',
|
||||
['!'] = 'red',
|
||||
t = 'red',
|
||||
},
|
||||
},
|
||||
|
||||
-- To be extra meticulous, we can also add some vim statusline syntax to
|
||||
-- control the padding and make sure our string is always at least 2
|
||||
-- characters long. Plus a nice Icon.
|
||||
provider = function(self)
|
||||
return ' ' .. self.mode_names[self.mode] .. '%)';
|
||||
end,
|
||||
|
||||
-- Same goes for the highlight. Now the foreground will change according to the current mode.
|
||||
hl = function(self)
|
||||
local mode = self.mode:sub(1, 1); -- get only the first mode character
|
||||
return { fg = self.mode_colors[mode], bold = true };
|
||||
end,
|
||||
|
||||
-- Re-evaluate the component only on ModeChanged event
|
||||
update = {
|
||||
'ModeChanged',
|
||||
},
|
||||
};
|
||||
|
||||
local FileNameBlock = {
|
||||
init = function(self)
|
||||
self.filename = vim.api.nvim_buf_get_name(0);
|
||||
end,
|
||||
};
|
||||
|
||||
-- FileNameBlock children
|
||||
local FileIcon = {
|
||||
init = function(self)
|
||||
local filename = self.filename;
|
||||
local extension = vim.fn.fnamemodify(filename, ':e');
|
||||
self.icon, self.icon_color =
|
||||
require('nvim-web-devicons').get_icon_color(filename, extension, { default = true });
|
||||
end,
|
||||
|
||||
provider = function(self)
|
||||
return self.icon and (self.icon .. ' ');
|
||||
end,
|
||||
|
||||
hl = function(self)
|
||||
return { fg = self.icon_color };
|
||||
end,
|
||||
};
|
||||
|
||||
local FileName = {
|
||||
provider = function(self)
|
||||
-- first, trim the pattern relative to the current directory. For other
|
||||
-- options, see :h filename-modifers
|
||||
local filename = vim.fn.fnamemodify(self.filename, ':.');
|
||||
if filename == '' then
|
||||
return '[No Name]';
|
||||
end;
|
||||
-- now, if the filename would occupy more than 1/4th of the available
|
||||
-- space, we trim the file path to its initials
|
||||
-- See Flexible Components section below for dynamic truncation
|
||||
if not conditions.width_percent_below(#filename, 0.25) then
|
||||
filename = vim.fn.pathshorten(filename);
|
||||
end;
|
||||
return filename;
|
||||
end,
|
||||
|
||||
hl = { fg = utils.get_highlight('Directory').fg },
|
||||
};
|
||||
|
||||
local FileFlags = {
|
||||
{
|
||||
condition = function()
|
||||
return vim.bo.modified;
|
||||
end,
|
||||
provider = '[+]',
|
||||
hl = { fg = 'green' },
|
||||
},
|
||||
{
|
||||
condition = function()
|
||||
return not vim.bo.modifiable or vim.bo.readonly;
|
||||
end,
|
||||
provider = '',
|
||||
hl = { fg = 'orange' },
|
||||
},
|
||||
};
|
||||
|
||||
local FileNameModifer = {
|
||||
hl = function()
|
||||
if vim.bo.modified then
|
||||
-- use `force` because we need to override the child's hl foreground
|
||||
return { fg = 'cyan', bold = true, force = true };
|
||||
end;
|
||||
end,
|
||||
};
|
||||
|
||||
-- let's add the children to our FileNameBlock component
|
||||
FileNameBlock = utils.insert(
|
||||
FileNameBlock,
|
||||
FileIcon,
|
||||
utils.insert(FileNameModifer, FileName), -- a new table where FileName is a child of FileNameModifier
|
||||
unpack(FileFlags), -- A small optimisation, since their parent does nothing
|
||||
{ provider = '%<' } -- this means that the statusline is cut here when there's not enough space
|
||||
);
|
||||
|
||||
local Ruler = {
|
||||
provider = ' line: %l col: %c',
|
||||
hl = { fg = 'green', bold = false },
|
||||
};
|
||||
|
||||
local ScrollRuler = {
|
||||
-- %l = current line number
|
||||
-- %L = number of lines in the buffer
|
||||
-- %c = column number
|
||||
-- %P = percentage through file of displayed window
|
||||
provider = '%P',
|
||||
};
|
||||
|
||||
local ScrollBar = {
|
||||
static = {
|
||||
sbar = { '▁', '▂', '▃', '▄', '▅', '▆', '▇', '█' },
|
||||
-- sbar = { '🭶', '🭷', '🭸', '🭹', '🭺', '🭻' }
|
||||
},
|
||||
|
||||
provider = function(self)
|
||||
local curr_line = vim.api.nvim_win_get_cursor(0)[1];
|
||||
local lines = vim.api.nvim_buf_line_count(0);
|
||||
local i = math.floor((curr_line - 1) / lines * #self.sbar) + 1;
|
||||
return string.rep(self.sbar[i], 2);
|
||||
end,
|
||||
|
||||
hl = { fg = 'cyan', bg = 'bright_bg' },
|
||||
};
|
||||
|
||||
local LSPActive = {
|
||||
condition = conditions.lsp_attached,
|
||||
update = { 'LspAttach', 'LspDetach' },
|
||||
|
||||
provider = function()
|
||||
local names = {};
|
||||
for _, server in pairs(vim.lsp.get_clients()) do
|
||||
table.insert(names, server.name);
|
||||
end;
|
||||
return ' [' .. table.concat(names, ' ') .. '] ';
|
||||
end,
|
||||
|
||||
hl = { fg = 'green', bold = false },
|
||||
};
|
||||
|
||||
local spinner_frames = { '⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏' };
|
||||
|
||||
-- From https://github.com/mhartington/dotfiles/blob/5961460e3a492f7815259a692fca5ca2a1df924a/config/nvim/lua/mh/statusline/lsp_status.lua#L4
|
||||
local function get_lsp_progress()
|
||||
local messages = require('lsp-status/messaging').messages;
|
||||
local buf_messages = messages();
|
||||
local msgs = {};
|
||||
|
||||
for _, msg in ipairs(buf_messages) do
|
||||
local contents;
|
||||
|
||||
if msg.progress then
|
||||
contents = msg.title;
|
||||
|
||||
if msg.spinner then
|
||||
contents = spinner_frames[(msg.spinner % #spinner_frames) + 1] .. ' ' .. contents;
|
||||
end;
|
||||
elseif msg.status then
|
||||
contents = msg.content;
|
||||
|
||||
if msg.uri then
|
||||
local space = math.min(60, math.floor(0.6 * vim.fn.winwidth(0)));
|
||||
local filename = vim.uri_to_fname(msg.uri);
|
||||
|
||||
filename = vim.fn.fnamemodify(filename, ':~:.');
|
||||
|
||||
if #filename > space then
|
||||
filename = vim.fn.pathshorten(filename);
|
||||
end;
|
||||
|
||||
contents = '(' .. filename .. ') ' .. contents;
|
||||
end;
|
||||
else
|
||||
contents = msg.content;
|
||||
end;
|
||||
|
||||
table.insert(msgs, contents);
|
||||
end;
|
||||
|
||||
return table.concat(msgs, ' ');
|
||||
end;
|
||||
|
||||
local LSPMessages = {
|
||||
provider = function()
|
||||
local progress = get_lsp_progress();
|
||||
|
||||
if progress == '' then
|
||||
return '';
|
||||
else
|
||||
return ' ' .. progress;
|
||||
end;
|
||||
end,
|
||||
hl = { fg = 'purple' },
|
||||
};
|
||||
|
||||
local Diagnostics = {
|
||||
condition = conditions.has_diagnostics,
|
||||
|
||||
static = {
|
||||
error_icon = ' ',
|
||||
warn_icon = ' ',
|
||||
info_icon = ' ',
|
||||
hint_icon = ' ',
|
||||
},
|
||||
|
||||
init = function(self)
|
||||
self.errors = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.ERROR });
|
||||
self.warnings = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.WARN });
|
||||
self.hints = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.HINT });
|
||||
self.info = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.INFO });
|
||||
end,
|
||||
|
||||
update = { 'DiagnosticChanged', 'BufEnter' },
|
||||
|
||||
{
|
||||
provider = function(self)
|
||||
-- 0 is just another output, we can decide to print it or not!
|
||||
return self.errors > 0 and (self.error_icon .. self.errors);
|
||||
end,
|
||||
hl = { fg = 'diag_error' },
|
||||
},
|
||||
{
|
||||
provider = function(self)
|
||||
return self.warnings > 0 and (self.warn_icon .. self.warnings);
|
||||
end,
|
||||
hl = { fg = 'diag_warn' },
|
||||
},
|
||||
{
|
||||
provider = function(self)
|
||||
return self.info > 0 and (self.info_icon .. self.info);
|
||||
end,
|
||||
hl = { fg = 'diag_info' },
|
||||
},
|
||||
{
|
||||
provider = function(self)
|
||||
return self.hints > 0 and (self.hint_icon .. self.hints);
|
||||
end,
|
||||
hl = { fg = 'diag_hint' },
|
||||
},
|
||||
};
|
||||
|
||||
local Git = {
|
||||
condition = conditions.is_git_repo,
|
||||
|
||||
init = function(self)
|
||||
self.status_dict = vim.b.gitsigns_status_dict;
|
||||
self.has_changes = self.status_dict.added ~= 0 or
|
||||
self.status_dict.removed ~= 0 or
|
||||
self.status_dict.changed ~= 0;
|
||||
end,
|
||||
|
||||
hl = { fg = 'orange' },
|
||||
|
||||
{ -- git branch name
|
||||
provider = function(self)
|
||||
return ' ' .. self.status_dict.head;
|
||||
end,
|
||||
hl = { bold = true },
|
||||
},
|
||||
-- You could handle delimiters, icons and counts similar to Diagnostics
|
||||
{
|
||||
condition = function(self)
|
||||
return self.has_changes;
|
||||
end,
|
||||
provider = '(',
|
||||
},
|
||||
{
|
||||
provider = function(self)
|
||||
local count = self.status_dict.added or 0;
|
||||
return count > 0 and ('+' .. count);
|
||||
end,
|
||||
hl = { fg = 'git_add' },
|
||||
},
|
||||
{
|
||||
provider = function(self)
|
||||
local count = self.status_dict.removed or 0;
|
||||
return count > 0 and ('-' .. count);
|
||||
end,
|
||||
hl = { fg = 'git_del' },
|
||||
},
|
||||
{
|
||||
provider = function(self)
|
||||
local count = self.status_dict.changed or 0;
|
||||
return count > 0 and ('~' .. count);
|
||||
end,
|
||||
hl = { fg = 'git_change' },
|
||||
},
|
||||
{
|
||||
condition = function(self)
|
||||
return self.has_changes;
|
||||
end,
|
||||
provider = ')',
|
||||
},
|
||||
};
|
||||
|
||||
local Align = { provider = '%=' };
|
||||
local Space = { provider = ' ' };
|
||||
|
||||
Left = utils.surround({ '', '' }, 'bright_bg', { ViMode, Diagnostics, LSPMessages });
|
||||
Middle = utils.surround({ '', '' }, 'bright_bg', { LSPActive, FileNameBlock, Ruler });
|
||||
Right = utils.surround({ '', '' }, 'bright_bg', { Git, Space, ScrollRuler, Space, ScrollBar });
|
||||
|
||||
local DefaultStatusline = {
|
||||
hl = { bg = 'dark_bg' },
|
||||
condition = function()
|
||||
return true;
|
||||
end,
|
||||
Left,
|
||||
Align,
|
||||
Middle,
|
||||
Align,
|
||||
Right,
|
||||
};
|
||||
|
||||
local StatusLines = {
|
||||
hl = function()
|
||||
if conditions.is_active() then
|
||||
return 'StatusLine';
|
||||
else
|
||||
return 'StatusLineNC';
|
||||
end;
|
||||
end,
|
||||
|
||||
-- the first statusline with no condition, or which condition returns true is used.
|
||||
-- think of it as a switch case with breaks to stop fallthrough.
|
||||
fallthrough = false,
|
||||
|
||||
DefaultStatusline,
|
||||
};
|
||||
|
||||
-- Make it global
|
||||
vim.opt.laststatus = 3;
|
||||
|
||||
require('heirline').setup({
|
||||
statusline = StatusLines,
|
||||
});
|
|
@ -1,63 +0,0 @@
|
|||
-- Override netrw
|
||||
vim.g.loaded_netrw = 0;
|
||||
vim.g.loaded_netrwPlugin = 0;
|
||||
|
||||
require('neo-tree').setup({
|
||||
close_if_last_window = true,
|
||||
enable_refresh_on_write = true,
|
||||
|
||||
window = {
|
||||
width = 22,
|
||||
},
|
||||
|
||||
filesystem = {
|
||||
use_libuv_file_watcher = true,
|
||||
group_empty_dirs = true,
|
||||
|
||||
filtered_items = {
|
||||
visible = false,
|
||||
hide_dotfiles = false,
|
||||
hide_gitignored = false,
|
||||
hide_by_name = {},
|
||||
hide_by_pattern = {},
|
||||
always_show = {},
|
||||
never_show = {},
|
||||
never_show_by_pattern = {},
|
||||
},
|
||||
},
|
||||
|
||||
source_selector = {
|
||||
winbar = true,
|
||||
statusline = false,
|
||||
},
|
||||
|
||||
follow_current_file = {
|
||||
enabled = true,
|
||||
leave_dirs_open = true,
|
||||
},
|
||||
});
|
||||
|
||||
local function is_neotree_open()
|
||||
local manager = require('neo-tree.sources.manager');
|
||||
local renderer = require('neo-tree.ui.renderer');
|
||||
local state = manager.get_state('filesystem');
|
||||
return renderer.window_exists(state);
|
||||
end;
|
||||
|
||||
-- Auto open Neo-Tree on big enough window
|
||||
vim.api.nvim_create_autocmd({ 'VimEnter', 'VimResized' }, {
|
||||
pattern = '*',
|
||||
callback = function()
|
||||
if vim.api.nvim_eval([[&columns]]) > 100 then
|
||||
if is_neotree_open() == false then
|
||||
vim.cmd[[Neotree show]];
|
||||
vim.cmd[[Neotree close]];
|
||||
vim.cmd[[Neotree show]];
|
||||
end;
|
||||
else
|
||||
if is_neotree_open() then
|
||||
vim.cmd[[Neotree close]];
|
||||
end;
|
||||
end;
|
||||
end,
|
||||
});
|
|
@ -1,179 +0,0 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
nvim-theme-src,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) fileContents optionals;
|
||||
inherit (config.vars) neovimIde;
|
||||
in {
|
||||
programs = {
|
||||
neovim = {
|
||||
extraPackages = builtins.attrValues {
|
||||
inherit (pkgs) bat;
|
||||
};
|
||||
|
||||
plugins =
|
||||
[
|
||||
{
|
||||
plugin = pkgs.vimPlugins.dracula-nvim.overrideAttrs {
|
||||
src = nvim-theme-src;
|
||||
};
|
||||
type = "lua";
|
||||
config =
|
||||
# lua
|
||||
''
|
||||
-- set dot icon in place of trailing whitespaces
|
||||
vim.opt.listchars = {
|
||||
tab = '→ ',
|
||||
trail = '•',
|
||||
extends = '⟩',
|
||||
precedes = '⟨',
|
||||
nbsp = '␣',
|
||||
};
|
||||
vim.opt.list = true;
|
||||
|
||||
-- Add visual indicator for trailing whitespaces
|
||||
vim.opt.fillchars = { eob = " " };
|
||||
vim.fn.matchadd('errorMsg', [[\s\+$]]);
|
||||
|
||||
vim.cmd.colorscheme('dracula');
|
||||
'';
|
||||
}
|
||||
{
|
||||
plugin = pkgs.vimPlugins.indent-blankline-nvim;
|
||||
type = "lua";
|
||||
config =
|
||||
# lua
|
||||
''
|
||||
--
|
||||
local highlight = {
|
||||
"RainbowRed",
|
||||
"RainbowYellow",
|
||||
"RainbowBlue",
|
||||
"RainbowOrange",
|
||||
"RainbowGreen",
|
||||
"RainbowViolet",
|
||||
"RainbowCyan",
|
||||
};
|
||||
|
||||
local hooks = require('ibl.hooks');
|
||||
hooks.register(hooks.type.HIGHLIGHT_SETUP, function()
|
||||
vim.api.nvim_set_hl(0, "RainbowRed", { fg = "#E06C75" });
|
||||
vim.api.nvim_set_hl(0, "RainbowYellow", { fg = "#E5C07B" });
|
||||
vim.api.nvim_set_hl(0, "RainbowBlue", { fg = "#61AFEF" });
|
||||
vim.api.nvim_set_hl(0, "RainbowOrange", { fg = "#D19A66" });
|
||||
vim.api.nvim_set_hl(0, "RainbowGreen", { fg = "#98C379" });
|
||||
vim.api.nvim_set_hl(0, "RainbowViolet", { fg = "#C678DD" });
|
||||
vim.api.nvim_set_hl(0, "RainbowCyan", { fg = "#56B6C2" });
|
||||
end);
|
||||
|
||||
require('ibl').setup({
|
||||
indent = {
|
||||
highlight = highlight,
|
||||
char = "▏",
|
||||
},
|
||||
});
|
||||
'';
|
||||
}
|
||||
|
||||
{
|
||||
plugin = pkgs.vimPlugins.nvim-highlight-colors;
|
||||
type = "lua";
|
||||
config =
|
||||
# lua
|
||||
''
|
||||
-- Ensure termguicolors is enabled if not already
|
||||
vim.opt.termguicolors = true;
|
||||
|
||||
require('nvim-highlight-colors').setup({});
|
||||
'';
|
||||
}
|
||||
|
||||
# Deps of heirline config
|
||||
pkgs.vimPlugins.nvim-web-devicons
|
||||
{
|
||||
plugin = pkgs.vimPlugins.heirline-nvim;
|
||||
type = "lua";
|
||||
config = fileContents ./plugins/heirline.lua;
|
||||
}
|
||||
]
|
||||
++ optionals neovimIde [
|
||||
{
|
||||
plugin = pkgs.vimPlugins.neo-tree-nvim;
|
||||
type = "lua";
|
||||
config = fileContents ./plugins/neotree.lua;
|
||||
}
|
||||
{
|
||||
plugin = pkgs.vimPlugins.codewindow-nvim;
|
||||
type = "lua";
|
||||
config =
|
||||
# lua
|
||||
''
|
||||
--
|
||||
local codewindow = require('codewindow');
|
||||
|
||||
codewindow.setup({
|
||||
auto_enable = false,
|
||||
minimap_width = 8,
|
||||
relative = 'editor',
|
||||
window_border = 'none',
|
||||
exclude_filetypes = { 'help' },
|
||||
});
|
||||
|
||||
vim.api.nvim_create_autocmd({ 'VimEnter', 'VimResized' }, {
|
||||
pattern = '*',
|
||||
callback = function()
|
||||
if vim.api.nvim_win_get_width(0) < 88 then
|
||||
codewindow.close_minimap();
|
||||
else
|
||||
codewindow.open_minimap();
|
||||
end
|
||||
end,
|
||||
});
|
||||
'';
|
||||
}
|
||||
{
|
||||
plugin = pkgs.vimPlugins.transparent-nvim;
|
||||
type = "lua";
|
||||
config =
|
||||
# lua
|
||||
''
|
||||
require('transparent').setup({
|
||||
groups = {
|
||||
'Normal',
|
||||
'NormalNC',
|
||||
'Comment',
|
||||
'Constant',
|
||||
'Special',
|
||||
'Identifier',
|
||||
'Statement',
|
||||
'PreProc',
|
||||
'Type',
|
||||
'Underlined',
|
||||
'Todo',
|
||||
'String',
|
||||
'Function',
|
||||
'Conditional',
|
||||
'Repeat',
|
||||
'Operator',
|
||||
'Structure',
|
||||
'LineNr',
|
||||
'NonText',
|
||||
'SignColumn',
|
||||
'CursorLine',
|
||||
'CursorLineNr',
|
||||
'StatusLine',
|
||||
'StatusLineNC',
|
||||
'EndOfBuffer',
|
||||
},
|
||||
extra_groups = {},
|
||||
exclude_groups = {},
|
||||
});
|
||||
'';
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
{pkgs, ...}: {
|
||||
programs.neovim.plugins = [
|
||||
{
|
||||
plugin = pkgs.vimPlugins.nvim-treesitter-context;
|
||||
type = "lua";
|
||||
config =
|
||||
# lua
|
||||
''
|
||||
require('treesitter-context').setup({
|
||||
enable = true,
|
||||
max_lines = 3,
|
||||
min_window_height = 20,
|
||||
});
|
||||
|
||||
vim.cmd.hi('TreesitterContextBottom', 'gui=underline guisp=Grey');
|
||||
'';
|
||||
}
|
||||
|
||||
pkgs.vimPlugins.nvim-treesitter-textobjects
|
||||
|
||||
{
|
||||
plugin = pkgs.vimPlugins.nvim-treesitter.withAllGrammars;
|
||||
type = "lua";
|
||||
config =
|
||||
# lua
|
||||
''
|
||||
require('nvim-treesitter.configs').setup({
|
||||
highlight = { enable = true },
|
||||
indent = { enable = true },
|
||||
});
|
||||
'';
|
||||
}
|
||||
];
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
{nix-index-db, ...}: {
|
||||
imports = [nix-index-db.hmModules.nix-index];
|
||||
|
||||
programs = {
|
||||
nix-index-database.comma.enable = true;
|
||||
nix-index = {
|
||||
enable = true;
|
||||
enableBashIntegration = true;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
{pkgs, ...}: {
|
||||
programs = {
|
||||
# Make sure we have color support
|
||||
bash.shellAliases.tmux = "tmux -2";
|
||||
|
||||
tmux = {
|
||||
enable = true;
|
||||
mouse = true;
|
||||
keyMode = "vi";
|
||||
terminal = "tmux-256color";
|
||||
newSession = true;
|
||||
historyLimit = 30000;
|
||||
|
||||
plugins = builtins.attrValues {
|
||||
inherit (pkgs.tmuxPlugins) dracula;
|
||||
};
|
||||
|
||||
extraConfig =
|
||||
# bash
|
||||
''
|
||||
bind-key -n Home send Escape "OH"
|
||||
bind-key -n End send Escape "OF"
|
||||
bind -T root WheelUpPane if-shell -F -t = "#{alternate_on}" "send-keys -M" "select-pane -t =; copy-mode -e; send-keys -M"
|
||||
bind -T root WheelDownPane if-shell -F -t = "#{alternate_on}" "send-keys -M" "select-pane -t =; send-keys -M"
|
||||
|
||||
set -ga terminal-overrides ',xterm*:smcup@:rmcup@'
|
||||
set -ga terminal-overrides ",*256col*:Tc"
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
pkgs,
|
||||
self,
|
||||
...
|
||||
}: {
|
||||
home.packages = [self.packages.${pkgs.system}.trash-d];
|
||||
|
||||
programs.bash.shellAliases.rm = "trash";
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) foldl isList mergeAttrsWithFunc optionals unique;
|
||||
|
||||
mergeAttrsList = list:
|
||||
foldl (mergeAttrsWithFunc (a: b:
|
||||
if isList a && isList b
|
||||
then unique (a ++ b)
|
||||
else b)) {}
|
||||
list;
|
||||
in {
|
||||
environment.systemPackages = [
|
||||
(pkgs.writeShellApplication {
|
||||
name = "rebuild-no-cache";
|
||||
runtimeInputs = [config.programs.nh.package];
|
||||
text = ''
|
||||
nh os switch -- --option binary-caches "https://cache.nixos.org" "$@"
|
||||
'';
|
||||
})
|
||||
];
|
||||
|
||||
nix = {
|
||||
settings = let
|
||||
mkSubstituterConf = url: key: {
|
||||
substituters = [url];
|
||||
trusted-public-keys = optionals (key != null) [key];
|
||||
};
|
||||
in
|
||||
mergeAttrsList ([
|
||||
(mkSubstituterConf "https://cache.nixos.org" "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=")
|
||||
(mkSubstituterConf "https://hyprland.cachix.org" "hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc=")
|
||||
(mkSubstituterConf "https://nix-gaming.cachix.org" "nix-gaming.cachix.org-1:nbjlureqMbRAxR1gJ/f3hxemL9svXaZF/Ees8vCUUs4=")
|
||||
(mkSubstituterConf "https://nixpkgs-wayland.cachix.org" "nixpkgs-wayland.cachix.org-1:3lwxaILxMRkVhehr5StQprHdEo4IrE8sRho9R9HOLYA=")
|
||||
(mkSubstituterConf "https://nix-community.cachix.org" "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=")
|
||||
(mkSubstituterConf "https://viperml.cachix.org" "viperml.cachix.org-1:qZhKBMTfmcLL+OG6fj/hzsMEedgKvZVFRRAhq7j8Vh8=")
|
||||
(mkSubstituterConf "https://cuda-maintainers.cachix.org" "cuda-maintainers.cachix.org-1:0dq3bujKpuEPMCX6U4WylrUDZ9JyUG0VpVZa7CNfq5E=")
|
||||
]
|
||||
++ optionals (!config.services.nix-serve.enable) [
|
||||
(mkSubstituterConf "https://cache.nelim.org" "cache.nelim.org:JmFqkUdH11EA9EZOFAGVHuRYp7EbsdJDHvTQzG2pPyY=")
|
||||
]);
|
||||
};
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
{...}: {
|
||||
imports = [
|
||||
./cachix.nix
|
||||
./locale.nix
|
||||
./locate.nix
|
||||
./global.nix
|
||||
];
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
nixpkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (config.sops.secrets) access-token;
|
||||
inherit (lib) hasAttr optionalString;
|
||||
in {
|
||||
# Minimize dowloads of indirect nixpkgs flakes
|
||||
nix = {
|
||||
registry.nixpkgs.flake = nixpkgs;
|
||||
nixPath = ["nixpkgs=${nixpkgs}"];
|
||||
|
||||
extraOptions =
|
||||
optionalString (hasAttr "sops" config)
|
||||
"!include ${access-token.path}";
|
||||
};
|
||||
|
||||
# Global hm settings
|
||||
home-manager.useGlobalPkgs = true;
|
||||
home-manager.useUserPackages = true;
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
{pkgs, ...}: {
|
||||
fonts = {
|
||||
fontconfig = {
|
||||
enable = true;
|
||||
defaultFonts = {
|
||||
emoji = ["Noto Color Emoji"];
|
||||
monospace = ["JetBrainsMono Nerd Font"];
|
||||
sansSerif = ["Noto Nerd Font"];
|
||||
serif = ["Noto Nerd Font"];
|
||||
};
|
||||
};
|
||||
|
||||
packages =
|
||||
[
|
||||
(pkgs.nerdfonts.override {
|
||||
fonts = [
|
||||
"JetBrainsMono"
|
||||
"Go-Mono"
|
||||
"Iosevka"
|
||||
"NerdFontsSymbolsOnly"
|
||||
"SpaceMono"
|
||||
"Ubuntu"
|
||||
"Noto"
|
||||
];
|
||||
})
|
||||
]
|
||||
++ (builtins.attrValues {
|
||||
inherit
|
||||
(pkgs)
|
||||
noto-fonts
|
||||
noto-fonts-cjk-sans
|
||||
noto-fonts-emoji
|
||||
liberation_ttf
|
||||
font-awesome
|
||||
meslo-lgs-nf
|
||||
jetbrains-mono
|
||||
ubuntu_font_family
|
||||
;
|
||||
});
|
||||
};
|
||||
|
||||
# Select internationalisation properties.
|
||||
i18n.defaultLocale = "en_CA.UTF-8";
|
||||
console.useXkbConfig = true;
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (config.vars) mainUser;
|
||||
cfg = config.services.locate;
|
||||
|
||||
locateGroup = lib.getName cfg.package.name;
|
||||
|
||||
locate = "${cfg.package}/bin/locate";
|
||||
updatedb = "${cfg.package}/bin/updatedb";
|
||||
|
||||
database = "/var/lib/locate/locatedb";
|
||||
pruneFS = builtins.concatStringsSep " " cfg.pruneFS;
|
||||
pruneNames = builtins.concatStringsSep " " cfg.pruneNames;
|
||||
prunePaths = builtins.concatStringsSep " " cfg.prunePaths;
|
||||
|
||||
updatedbBin = ''
|
||||
${updatedb} -o ${database} --prunefs "${pruneFS}" \
|
||||
--prunepaths "${prunePaths}" --prunenames "${pruneNames}"
|
||||
'';
|
||||
in {
|
||||
users.users.${mainUser}.extraGroups = [
|
||||
locateGroup
|
||||
];
|
||||
|
||||
# TODO: add timer
|
||||
systemd.services.locate = {
|
||||
wantedBy = ["default.target"];
|
||||
serviceConfig = {
|
||||
User = mainUser;
|
||||
Group = locateGroup;
|
||||
StateDirectory = "locate";
|
||||
StateDirectoryMode = "0770";
|
||||
ExecStart = updatedbBin;
|
||||
};
|
||||
};
|
||||
|
||||
home-manager.users.${mainUser}.programs.bash.shellAliases = {
|
||||
locate = "${pkgs.writeShellScriptBin "lct" ''
|
||||
exec ${locate} -d ${database} "$@" 2> >(grep -v "/var/cache/locatedb")
|
||||
''}/bin/lct";
|
||||
|
||||
updatedb = updatedbBin;
|
||||
};
|
||||
|
||||
services.locate = {
|
||||
enable = true;
|
||||
package = pkgs.mlocate;
|
||||
localuser = null;
|
||||
interval = "never";
|
||||
|
||||
prunePaths = [
|
||||
"/var/lib/flatpak"
|
||||
|
||||
# Defaults
|
||||
"/tmp"
|
||||
"/var/tmp"
|
||||
"/var/cache"
|
||||
"/var/lock"
|
||||
"/var/run"
|
||||
"/var/spool"
|
||||
"/nix/var/log/nix"
|
||||
];
|
||||
|
||||
pruneNames = [
|
||||
"node_modules"
|
||||
|
||||
# Defaults
|
||||
".bzr"
|
||||
".cache"
|
||||
".git"
|
||||
".hg"
|
||||
".svn"
|
||||
];
|
||||
};
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
./vars
|
||||
./modules/global.nix
|
||||
./packages.nix
|
||||
];
|
||||
|
||||
nix = {
|
||||
# Edit nix.conf
|
||||
extraOptions = ''
|
||||
experimental-features = nix-command flakes
|
||||
keep-outputs = true
|
||||
keep-derivations = true
|
||||
warn-dirty = false
|
||||
'';
|
||||
|
||||
substituters = [
|
||||
# Nix-community
|
||||
"https://nix-community.cachix.org"
|
||||
];
|
||||
trustedPublicKeys = [
|
||||
# Nix-community
|
||||
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||||
];
|
||||
};
|
||||
|
||||
# Global hm settings
|
||||
home-manager.config = {
|
||||
imports = [
|
||||
# Make the vars be the same on Nix and HM
|
||||
{
|
||||
options.vars = lib.mkOption {
|
||||
type = lib.types.attrs;
|
||||
readOnly = true;
|
||||
default = config.vars;
|
||||
};
|
||||
}
|
||||
|
||||
./home
|
||||
|
||||
{
|
||||
programs.bash.sessionVariables = {
|
||||
FLAKE = config.environment.variables.FLAKE;
|
||||
};
|
||||
|
||||
programs.bash.shellAliases = {
|
||||
# Make ping work on nix-on-droid
|
||||
# https://github.com/nix-community/nix-on-droid/issues/185#issuecomment-1659294700
|
||||
ping = "/android/system/bin/linker64 /android/system/bin/ping";
|
||||
|
||||
# SSH
|
||||
# Desktop
|
||||
pc = "ssh -t matt@100.64.0.6 'tmux -2u new -At phone'";
|
||||
|
||||
# NAS
|
||||
nos = "ssh -t matt@100.64.0.4 'tmux -2u new -At phone'";
|
||||
|
||||
# Experimenting server
|
||||
servivi = "ssh -t matt@100.64.0.7 'tmux -2u new -At phone'";
|
||||
|
||||
# Home-assistant
|
||||
homie = "ssh -t matt@100.64.0.10 'tmux -2u new -At phone'";
|
||||
|
||||
# Cluster nodes
|
||||
thingone = "ssh -t matt@100.64.0.8 'tmux -2u new -At phone'";
|
||||
thingtwo = "ssh -t matt@100.64.0.9 'tmux -2u new -At phone'";
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
home.stateVersion = "23.05";
|
||||
};
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
inputs @ {
|
||||
pkgs,
|
||||
self,
|
||||
...
|
||||
}: {
|
||||
nixpkgs.overlays =
|
||||
(map (i: inputs.${i}.overlays.default) [
|
||||
"discord-overlay"
|
||||
"grim-hyprland"
|
||||
"nixpkgs-wayland"
|
||||
])
|
||||
++ (builtins.attrValues {
|
||||
inherit
|
||||
(self.overlays)
|
||||
xdg-desktop-portal-kde
|
||||
;
|
||||
});
|
||||
|
||||
environment.systemPackages =
|
||||
(builtins.attrValues {
|
||||
inherit
|
||||
(self.packages.${pkgs.system})
|
||||
pokemon-colorscripts
|
||||
repl
|
||||
;
|
||||
|
||||
inherit
|
||||
(pkgs.nodePackages)
|
||||
undollar
|
||||
;
|
||||
|
||||
inherit (pkgs) alejandra;
|
||||
|
||||
# Archiving
|
||||
inherit
|
||||
(pkgs)
|
||||
zip
|
||||
unzip
|
||||
p7zip
|
||||
bzip2
|
||||
gzip
|
||||
gnutar
|
||||
xz
|
||||
;
|
||||
|
||||
# File management
|
||||
inherit
|
||||
(pkgs)
|
||||
findutils
|
||||
diffutils
|
||||
util-linux
|
||||
which
|
||||
imagemagick
|
||||
;
|
||||
|
||||
# Networking
|
||||
inherit (pkgs.dig) dnsutils;
|
||||
inherit
|
||||
(pkgs)
|
||||
arp-scan
|
||||
openssh
|
||||
rsync
|
||||
wget
|
||||
gnupg
|
||||
;
|
||||
|
||||
# Misc CLI stuff
|
||||
inherit
|
||||
(pkgs)
|
||||
hydra-check
|
||||
killall
|
||||
nix-output-monitor
|
||||
nix-melt
|
||||
progress
|
||||
tree
|
||||
gnugrep
|
||||
gnused
|
||||
;
|
||||
|
||||
# Expected Stuff
|
||||
inherit
|
||||
(pkgs)
|
||||
hostname
|
||||
man
|
||||
perl
|
||||
tzdata
|
||||
;
|
||||
})
|
||||
++ [
|
||||
# This could help as well: nix derivation show -r /run/current-system
|
||||
(pkgs.writeShellApplication {
|
||||
name = "listDerivs";
|
||||
text = ''
|
||||
exec nix-store --query --requisites /run/current-system | cut -d- -f2- | sort -u
|
||||
'';
|
||||
})
|
||||
|
||||
(pkgs.writeShellApplication {
|
||||
name = "from";
|
||||
|
||||
runtimeInputs = builtins.attrValues {
|
||||
inherit
|
||||
(pkgs)
|
||||
coreutils
|
||||
which
|
||||
;
|
||||
};
|
||||
|
||||
text = ''
|
||||
for var do
|
||||
realpath "$(which "$var")"
|
||||
done
|
||||
'';
|
||||
})
|
||||
];
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkDefault mkOption types;
|
||||
flakeDir = config.environment.variables.FLAKE;
|
||||
cfg = config.vars;
|
||||
in {
|
||||
options.vars = {
|
||||
mainUser = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
Username that was defined at the initial setup process
|
||||
'';
|
||||
};
|
||||
|
||||
hostName = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
Hostname that was defined at the initial setup process
|
||||
'';
|
||||
};
|
||||
|
||||
promptMainColor = mkOption {
|
||||
type = types.enum (import ./prompt-schemes.nix {});
|
||||
default = "purple";
|
||||
};
|
||||
|
||||
promptColors = mkOption {
|
||||
description = ''
|
||||
Colors used in starship prompt
|
||||
'';
|
||||
|
||||
default = import ./prompt-schemes.nix {color = cfg.promptMainColor;};
|
||||
|
||||
readOnly = true;
|
||||
type = types.submodule {
|
||||
options = let
|
||||
inherit (types) str;
|
||||
in {
|
||||
textColor = mkOption {type = str;};
|
||||
firstColor = mkOption {type = str;};
|
||||
secondColor = mkOption {type = str;};
|
||||
thirdColor = mkOption {type = str;};
|
||||
fourthColor = mkOption {type = str;};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
configDir = mkOption {
|
||||
type = types.str;
|
||||
default = "${flakeDir}/devices/${cfg.hostName}/config";
|
||||
description = ''
|
||||
The path to where most of the devices' configs are in the .nix folder
|
||||
'';
|
||||
};
|
||||
|
||||
neovimIde = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
environment.variables.FLAKE = mkDefault "/home/${cfg.mainUser}/.nix";
|
||||
};
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
{color ? null}: let
|
||||
inherit (builtins) attrNames removeAttrs;
|
||||
|
||||
schemes = {
|
||||
"purple" = {
|
||||
textColor = "#090c0c";
|
||||
firstColor = "#bd93f9";
|
||||
secondColor = "#715895";
|
||||
thirdColor = "#382c4a";
|
||||
fourthColor = "#120e18";
|
||||
};
|
||||
|
||||
"green" = {
|
||||
textColor = "#090c0c";
|
||||
firstColor = "#78ae66";
|
||||
secondColor = "#567c49";
|
||||
thirdColor = "#334a2c";
|
||||
fourthColor = "#11180e";
|
||||
};
|
||||
|
||||
"red" = {
|
||||
textColor = "#090c0c";
|
||||
firstColor = "#e04242";
|
||||
secondColor = "#9c2e2e";
|
||||
thirdColor = "#591a1a";
|
||||
fourthColor = "#160606";
|
||||
};
|
||||
|
||||
"blue" = {
|
||||
textColor = "#090c0c";
|
||||
firstColor = "#6684ee";
|
||||
secondColor = "#475ca6";
|
||||
thirdColor = "#28345f";
|
||||
fourthColor = "#010617";
|
||||
};
|
||||
|
||||
"orange" = {
|
||||
textColor = "#090c0c";
|
||||
firstColor = "#ff9c42";
|
||||
secondColor = "#c66b00";
|
||||
thirdColor = "#874500";
|
||||
fourthColor = "#3a1c00";
|
||||
};
|
||||
|
||||
"yellow" = {
|
||||
textColor = "#090c0c";
|
||||
firstColor = "#ffea42";
|
||||
secondColor = "#d4c300";
|
||||
thirdColor = "#8f8b00";
|
||||
fourthColor = "#3e3c00";
|
||||
};
|
||||
|
||||
"cyan" = {
|
||||
textColor = "#090c0c";
|
||||
firstColor = "#42eaff";
|
||||
secondColor = "#00a2b8";
|
||||
thirdColor = "#005768";
|
||||
fourthColor = "#001f26";
|
||||
};
|
||||
|
||||
"pink" = {
|
||||
textColor = "#090c0c";
|
||||
firstColor = "#ff42cb";
|
||||
secondColor = "#b80073";
|
||||
thirdColor = "#6b003f";
|
||||
fourthColor = "#2d0017";
|
||||
};
|
||||
|
||||
# Template
|
||||
"color" = {
|
||||
textColor = "#090c0c";
|
||||
firstColor = "";
|
||||
secondColor = "";
|
||||
thirdColor = "";
|
||||
fourthColor = "";
|
||||
};
|
||||
};
|
||||
in
|
||||
if ! isNull color
|
||||
then schemes.${color}
|
||||
else attrNames (removeAttrs schemes ["color"])
|
13
config/ags/bin/heart.sh
Executable file
13
config/ags/bin/heart.sh
Executable file
|
@ -0,0 +1,13 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
FILE="$HOME/.config/.heart"
|
||||
|
||||
toggle() {
|
||||
if grep -q "$FILE"; then
|
||||
echo > "$FILE"
|
||||
else
|
||||
echo >> "$FILE"
|
||||
fi
|
||||
}
|
||||
|
||||
[[ "$1" == "toggle" ]] && toggle
|
15
config/ags/bin/launch-app.sh
Executable file
15
config/ags/bin/launch-app.sh
Executable file
|
@ -0,0 +1,15 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
APP="$1"
|
||||
EXEC="$2"
|
||||
|
||||
if [[ "$APP" == "thunderbird" ]]; then
|
||||
hyprctl dispatch togglespecialworkspace thunder
|
||||
elif [[ "$APP" == "Spotify" ]]; then
|
||||
hyprctl dispatch togglespecialworkspace spot
|
||||
elif [[ $(hyprctl clients | grep "$APP") != "" ]]; then
|
||||
hyprctl dispatch focuswindow "^($APP)$"
|
||||
else
|
||||
hyprctl dispatch workspace empty
|
||||
hyprctl dispatch exec "$EXEC"
|
||||
fi
|
30
config/ags/bin/osk-toggle.sh
Executable file
30
config/ags/bin/osk-toggle.sh
Executable file
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
state () {
|
||||
if [[ $(busctl get-property --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 Visible) == "b true" ]]; then
|
||||
echo "Running"
|
||||
else
|
||||
echo "Stopped"
|
||||
fi
|
||||
}
|
||||
|
||||
toggle () {
|
||||
if [[ $(busctl get-property --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 Visible) == "b true" ]]; then
|
||||
echo "Running"
|
||||
busctl call --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 SetVisible b false
|
||||
else
|
||||
echo "Stopped"
|
||||
busctl call --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 SetVisible b true
|
||||
fi
|
||||
}
|
||||
|
||||
if [[ $1 == "getState" ]]; then
|
||||
while true; do
|
||||
sleep 0.2
|
||||
state
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ $1 == "toggle" ]];then
|
||||
toggle
|
||||
fi
|
33
config/ags/bin/qs-toggles.sh
Executable file
33
config/ags/bin/qs-toggles.sh
Executable file
|
@ -0,0 +1,33 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
radio_status () {
|
||||
radio_status=$(nmcli radio wifi)
|
||||
if [[ $radio_status == "enabled" ]]; then
|
||||
echo "on"
|
||||
else
|
||||
echo "off"
|
||||
fi
|
||||
}
|
||||
|
||||
if [[ $1 == "toggle-radio" ]]; then
|
||||
stat=$(radio_status)
|
||||
if [[ $stat == "on" ]]; then
|
||||
nmcli radio wifi off
|
||||
else
|
||||
nmcli radio wifi on
|
||||
fi
|
||||
fi
|
||||
|
||||
FILE='/home/matt/.config/.bluetooth'
|
||||
get_state() {
|
||||
if [[ "$(rfkill list | grep -A 1 hci0 | grep -o no)" == "no" ]]; then
|
||||
echo " " > "$FILE"
|
||||
else
|
||||
echo " " > "$FILE"
|
||||
fi
|
||||
}
|
||||
|
||||
if [[ "$1" == "blue-toggle" ]]; then
|
||||
rfkill toggle bluetooth
|
||||
get_state
|
||||
fi
|
10
config/ags/bin/startup.sh
Executable file
10
config/ags/bin/startup.sh
Executable file
|
@ -0,0 +1,10 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
## Make bluetooth status persistent between reboots
|
||||
if [[ ! -f "$HOME/.config/.bluetooth" ]]; then
|
||||
echo > "$FILE"
|
||||
fi
|
||||
|
||||
if grep -q "$HOME/.config/.bluetooth"; then
|
||||
rfkill block bluetooth
|
||||
fi
|
38
config/ags/bin/tablet-toggle.sh
Executable file
38
config/ags/bin/tablet-toggle.sh
Executable file
|
@ -0,0 +1,38 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
tablet() {
|
||||
gsettings set org.gnome.desktop.a11y.applications screen-keyboard-enabled true
|
||||
|
||||
brightnessctl -d tpacpi::kbd_backlight s 0
|
||||
|
||||
"$HYPR_PATH"/autorotate.sh &
|
||||
|
||||
evtest --grab "/dev/input/by-path/platform-i8042-serio-0-event-kbd" &
|
||||
evtest --grab "/dev/input/by-path/platform-i8042-serio-1-event-mouse" &
|
||||
evtest --grab "/dev/input/by-path/platform-AMDI0010:02-event-mouse" &
|
||||
evtest --grab "/dev/input/by-path/platform-thinkpad_acpi-event" &
|
||||
evtest --grab "/dev/video-bus" &
|
||||
}
|
||||
|
||||
laptop() {
|
||||
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
|
||||
}
|
||||
|
||||
toggle () {
|
||||
if [[ "$(gsettings get org.gnome.desktop.a11y.applications screen-keyboard-enabled)" == "false" ]]; then
|
||||
echo "Tablet"
|
||||
tablet > /dev/null
|
||||
else
|
||||
echo "Laptop"
|
||||
laptop > /dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
[[ $1 == "toggle" ]] && toggle
|
||||
[[ $1 == "laptop" ]] && laptop
|
||||
[[ $1 == "tablet" ]] && tablet
|
44
config/ags/config.js
Normal file
44
config/ags/config.js
Normal file
|
@ -0,0 +1,44 @@
|
|||
import { exec, execAsync } from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
import { Powermenu } from './js/powermenu.js';
|
||||
import { Bar } from './js/bar/main.js';
|
||||
import { NotificationCenter } from './js/notifications/center.js';
|
||||
import { NotificationsPopupList } from './js/notifications/popup.js'
|
||||
import { Calendar } from './js/date.js';
|
||||
import { QuickSettings } from './js/quick-settings/main.js';
|
||||
import Overview from './js/overview/main.js';
|
||||
import AppLauncher from './js/applauncher/main.js';
|
||||
|
||||
import { Closer, closeAll } from './js/misc/closer.js';
|
||||
ags.App.closeAll = () => closeAll();
|
||||
|
||||
const scss = ags.App.configDir + '/scss/main.scss';
|
||||
const css = ags.App.configDir + '/style.css';
|
||||
|
||||
exec(`sassc ${scss} ${css}`);
|
||||
|
||||
execAsync(['bash', '-c', '$AGS_PATH/startup.sh']).catch(print);
|
||||
|
||||
export default {
|
||||
style: css,
|
||||
notificationPopupTimeout: 5000,
|
||||
cacheNotificationActions: true,
|
||||
closeWindowDelay: {
|
||||
'quick-settings': 500,
|
||||
'notification-center': 500,
|
||||
'calendar': 500,
|
||||
'powermenu': 500,
|
||||
'overview': 500,
|
||||
'applauncher': 500,
|
||||
},
|
||||
windows: [
|
||||
Powermenu,
|
||||
Bar,
|
||||
Closer,
|
||||
NotificationCenter,
|
||||
NotificationsPopupList,
|
||||
Calendar,
|
||||
QuickSettings,
|
||||
Overview,
|
||||
AppLauncher,
|
||||
],
|
||||
};
|
134
config/ags/js/applauncher/main.js
Normal file
134
config/ags/js/applauncher/main.js
Normal file
|
@ -0,0 +1,134 @@
|
|||
const { App } = ags;
|
||||
const { Applications } = ags.Service;
|
||||
const { Label, Box, Icon, Button, Scrollable, Entry, Window, EventBox } = ags.Widget;
|
||||
|
||||
import { Separator } from '../misc/separator.js';
|
||||
import { PopUp } from '../misc/popup.js';
|
||||
|
||||
const icons = {
|
||||
apps: {
|
||||
apps: 'view-app-grid-symbolic',
|
||||
search: 'preferences-system-search-symbolic',
|
||||
}
|
||||
};
|
||||
|
||||
const AppItem = (app, window) => {
|
||||
if (app.app.get_string('Icon') == 'Nextcloud')
|
||||
return;
|
||||
|
||||
return Button({
|
||||
className: 'app',
|
||||
connections: [['clicked', () => {
|
||||
App.closeWindow(window);
|
||||
app.launch();
|
||||
}]],
|
||||
child: Box({
|
||||
children: [
|
||||
Icon({
|
||||
icon: app.app.get_string('Icon'),
|
||||
size: 42,
|
||||
}),
|
||||
Box({
|
||||
vertical: true,
|
||||
children: [
|
||||
Label({
|
||||
className: 'title',
|
||||
label: app.name,
|
||||
xalign: 0,
|
||||
valign: 'center',
|
||||
ellipsize: 3,
|
||||
}),
|
||||
Label({
|
||||
className: 'description',
|
||||
label: app.description || '',
|
||||
wrap: true,
|
||||
xalign: 0,
|
||||
justification: 'left',
|
||||
valign: 'center',
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
const Applauncher = ({ windowName = 'applauncher' } = {}) => {
|
||||
const list = Box({ vertical: true });
|
||||
const placeholder = Label({
|
||||
label: " Couldn't find a match",
|
||||
className: 'placeholder',
|
||||
});
|
||||
const entry = Entry({
|
||||
hexpand: true,
|
||||
placeholderText: 'Search',
|
||||
onAccept: ({ text }) => {
|
||||
const list = Applications.query(text);
|
||||
if (list[0]) {
|
||||
App.toggleWindow(windowName);
|
||||
list[0].launch();
|
||||
}
|
||||
},
|
||||
onChange: ({ text }) => {
|
||||
list.children = Applications.query(text).map(app => [
|
||||
Separator(4),
|
||||
AppItem(app, windowName),
|
||||
]).flat();
|
||||
list.add(Separator(4));
|
||||
list.show_all();
|
||||
|
||||
placeholder.visible = list.children.length === 1;
|
||||
},
|
||||
});
|
||||
|
||||
return Box({
|
||||
className: 'applauncher',
|
||||
properties: [['list', list]],
|
||||
vertical: true,
|
||||
children: [
|
||||
Box({
|
||||
className: 'header',
|
||||
children: [
|
||||
Icon(icons.apps.search),
|
||||
entry,
|
||||
],
|
||||
}),
|
||||
Scrollable({
|
||||
hscroll: 'never',
|
||||
child: Box({
|
||||
vertical: true,
|
||||
children: [list, placeholder],
|
||||
}),
|
||||
}),
|
||||
],
|
||||
connections: [[App, (_b, name, visible) => {
|
||||
if (name !== windowName)
|
||||
return;
|
||||
|
||||
entry.set_text('-'); // force onChange
|
||||
entry.set_text('');
|
||||
if (visible)
|
||||
entry.grab_focus();
|
||||
}]],
|
||||
});
|
||||
};
|
||||
|
||||
// FIXME: make it so I don't have to click to trigger onHoverLost
|
||||
export default Window({
|
||||
name: 'applauncher',
|
||||
popup: true,
|
||||
focusable: true,
|
||||
layer: 'overlay',
|
||||
child: EventBox({
|
||||
onHover: box => {
|
||||
box.get_parent().focusable = true
|
||||
},
|
||||
onHoverLost: box => {
|
||||
box.get_parent().focusable = false
|
||||
},
|
||||
child: PopUp({
|
||||
name: 'applauncher',
|
||||
child: Applauncher(),
|
||||
}),
|
||||
}),
|
||||
});
|
55
config/ags/js/bar/audio.js
Normal file
55
config/ags/js/bar/audio.js
Normal file
|
@ -0,0 +1,55 @@
|
|||
const { Audio } = ags.Service;
|
||||
const { Label, Box, Icon, Stack, Button, Slider } = ags.Widget;
|
||||
|
||||
import { Separator } from '../misc/separator.js';
|
||||
import { EventBox } from '../misc/cursorbox.js';
|
||||
|
||||
const items = {
|
||||
101: 'audio-volume-overamplified-symbolic',
|
||||
67: 'audio-volume-high-symbolic',
|
||||
34: 'audio-volume-medium-symbolic',
|
||||
1: 'audio-volume-low-symbolic',
|
||||
0: 'audio-volume-muted-symbolic',
|
||||
};
|
||||
|
||||
const SpeakerIndicator = params => Icon({
|
||||
...params,
|
||||
icon: '',
|
||||
connections: [[Audio, icon => {
|
||||
if (Audio.speaker) {
|
||||
if (Audio.speaker.isMuted) {
|
||||
icon.icon = items[0];
|
||||
}
|
||||
else {
|
||||
const vol = Audio.speaker.volume * 100;
|
||||
for (const threshold of [-1, 0, 33, 66, 100]) {
|
||||
if (vol > threshold + 1) {
|
||||
icon.icon = items[threshold + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 'speaker-changed']],
|
||||
});
|
||||
|
||||
const SpeakerPercentLabel = params => Label({
|
||||
...params,
|
||||
connections: [[Audio, label => {
|
||||
if (Audio.speaker) {
|
||||
label.label = Math.round(Audio.speaker.volume * 100) + '%';
|
||||
}
|
||||
}, 'speaker-changed']],
|
||||
});
|
||||
|
||||
export const AudioIndicator = EventBox({
|
||||
onPrimaryClickRelease: 'pavucontrol',
|
||||
className: 'toggle-off',
|
||||
child: Box({
|
||||
className: 'audio',
|
||||
children: [
|
||||
SpeakerIndicator(),
|
||||
Separator(5),
|
||||
SpeakerPercentLabel(),
|
||||
],
|
||||
}),
|
||||
});
|
58
config/ags/js/bar/battery.js
Normal file
58
config/ags/js/bar/battery.js
Normal file
|
@ -0,0 +1,58 @@
|
|||
const { Battery } = ags.Service;
|
||||
const { Label, Icon, Stack, Box } = ags.Widget;
|
||||
|
||||
import { Separator } from '../misc/separator.js';
|
||||
|
||||
const icons = charging => ([
|
||||
...Array.from({ length: 10 }, (_, i) => i * 10).map(i => ([
|
||||
`${i}`, Icon({
|
||||
className: `${i} ${charging ? 'charging' : 'discharging'}`,
|
||||
icon: `battery-level-${i}${charging ? '-charging' : ''}-symbolic`,
|
||||
}),
|
||||
])),
|
||||
['100', Icon({
|
||||
className: `100 ${charging ? 'charging' : 'discharging'}`,
|
||||
icon: `battery-level-100${charging ? '-charged' : ''}-symbolic`,
|
||||
})],
|
||||
]);
|
||||
|
||||
const Indicators = charging => Stack({
|
||||
items: icons(charging),
|
||||
connections: [[Battery, stack => {
|
||||
stack.shown = `${Math.floor(Battery.percent / 10) * 10}`;
|
||||
}]],
|
||||
});
|
||||
|
||||
const Indicator = ({
|
||||
charging = Indicators(true),
|
||||
discharging = Indicators(false),
|
||||
...params
|
||||
} = {}) => Stack({
|
||||
...params,
|
||||
className: 'battery-indicator',
|
||||
items: [
|
||||
['true', charging],
|
||||
['false', discharging],
|
||||
],
|
||||
connections: [[Battery, stack => {
|
||||
stack.shown = `${Battery.charging || Battery.charged}`;
|
||||
stack.toggleClassName('charging', Battery.charging);
|
||||
stack.toggleClassName('charged', Battery.charged);
|
||||
stack.toggleClassName('low', Battery.percent < 20);
|
||||
}]],
|
||||
});
|
||||
|
||||
const LevelLabel = params => Label({
|
||||
...params,
|
||||
className: 'label',
|
||||
connections: [[Battery, label => label.label = `${Battery.percent}%`]],
|
||||
});
|
||||
|
||||
export const BatteryIndicator = Box({
|
||||
className: 'toggle-off battery',
|
||||
children: [
|
||||
Indicator(),
|
||||
Separator(5),
|
||||
LevelLabel(),
|
||||
],
|
||||
});
|
35
config/ags/js/bar/brightness.js
Normal file
35
config/ags/js/bar/brightness.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
const { ProgressBar, Overlay, Box } = ags.Widget;
|
||||
const { execAsync } = ags.Utils;
|
||||
import { Separator } from '../misc/separator.js';
|
||||
import { Heart } from './heart.js';
|
||||
|
||||
export const Brightness = Overlay({
|
||||
setup: widget => {
|
||||
widget.set_tooltip_text('Brightness');
|
||||
},
|
||||
child: ProgressBar({
|
||||
className: 'toggle-off brightness',
|
||||
connections: [
|
||||
[200, progress => {
|
||||
execAsync('brightnessctl get').then(out => {
|
||||
let br = out / 255;
|
||||
if (br > 0.33) {
|
||||
progress.value = br;
|
||||
}
|
||||
else {
|
||||
progress.value = 0.33;
|
||||
}
|
||||
}).catch(print);
|
||||
}],
|
||||
],
|
||||
}),
|
||||
overlays: [
|
||||
Box({
|
||||
style: 'color: #CBA6F7;',
|
||||
children: [
|
||||
Separator(25),
|
||||
Heart,
|
||||
],
|
||||
}),
|
||||
],
|
||||
});
|
34
config/ags/js/bar/clock.js
Normal file
34
config/ags/js/bar/clock.js
Normal file
|
@ -0,0 +1,34 @@
|
|||
const { Box, Label } = ags.Widget;
|
||||
const { toggleWindow } = ags.App;
|
||||
const { DateTime } = imports.gi.GLib;
|
||||
|
||||
import { EventBox } from '../misc/cursorbox.js';
|
||||
|
||||
const ClockModule = ({
|
||||
interval = 1000,
|
||||
...params
|
||||
}) => Label({
|
||||
...params,
|
||||
className: 'clock',
|
||||
connections: [
|
||||
[interval, label => {
|
||||
var time = DateTime.new_now_local();
|
||||
label.label = time.format('%a. ') + time.get_day_of_month() + time.format(' %b. %H:%M');
|
||||
}],
|
||||
],
|
||||
});
|
||||
|
||||
export const Clock = EventBox({
|
||||
className: 'toggle-off',
|
||||
onPrimaryClickRelease: () => toggleWindow('calendar'),
|
||||
connections: [
|
||||
[ags.App, (box, windowName, visible) => {
|
||||
if (windowName == 'calendar') {
|
||||
box.toggleClassName('toggle-on', visible);
|
||||
}
|
||||
}],
|
||||
],
|
||||
child: Box({
|
||||
child: ClockModule({}),
|
||||
}),
|
||||
});
|
13
config/ags/js/bar/current-window.js
Normal file
13
config/ags/js/bar/current-window.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
const { Hyprland } = ags.Service;
|
||||
const { Label } = ags.Widget;
|
||||
const { Gtk } = imports.gi;
|
||||
|
||||
export const CurrentWindow = Label({
|
||||
style: 'color: #CBA6F7; font-size: 18px',
|
||||
truncate: 'end',
|
||||
connections: [
|
||||
[Hyprland, label => {
|
||||
label.label = Hyprland.active.client.title;
|
||||
}, 'changed'],
|
||||
],
|
||||
});
|
32
config/ags/js/bar/gesture.js
Normal file
32
config/ags/js/bar/gesture.js
Normal file
|
@ -0,0 +1,32 @@
|
|||
const { Window, CenterBox, EventBox, Button } = ags.Widget;
|
||||
const { openWindow } = ags.App;
|
||||
const { Gtk, Gdk } = imports.gi;
|
||||
const display = Gdk.Display.get_default();
|
||||
|
||||
export const Gesture = ({
|
||||
child,
|
||||
...params
|
||||
}) => {
|
||||
let w = EventBox({
|
||||
...params,
|
||||
});
|
||||
|
||||
let gesture = Gtk.GestureSwipe.new(w);
|
||||
|
||||
w.child = CenterBox({
|
||||
children: [
|
||||
child,
|
||||
],
|
||||
connections: [
|
||||
|
||||
[gesture, box => {
|
||||
const velocity = gesture.get_velocity()[1];
|
||||
if (velocity < -100)
|
||||
openWindow('quick-settings');
|
||||
}, 'update'],
|
||||
|
||||
],
|
||||
});
|
||||
|
||||
return w;
|
||||
};
|
26
config/ags/js/bar/heart.js
Normal file
26
config/ags/js/bar/heart.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
const { Box, Label } = ags.Widget;
|
||||
const { subprocess, execAsync } = ags.Utils;
|
||||
const deflisten = subprocess;
|
||||
|
||||
import { EventBox } from '../misc/cursorbox.js';
|
||||
|
||||
deflisten(
|
||||
['bash', '-c', 'tail -f /home/matt/.config/.heart'],
|
||||
(output) => {
|
||||
Heart.child.children[0].label = ' ' + output;
|
||||
},
|
||||
);
|
||||
export const Heart = EventBox({
|
||||
halign: 'center',
|
||||
onPrimaryClickRelease: () => {
|
||||
execAsync(['bash', '-c', '$AGS_PATH/heart.sh toggle']).catch(print);
|
||||
},
|
||||
child: Box({
|
||||
className: 'heart-toggle',
|
||||
vertical: false,
|
||||
|
||||
child: Label({
|
||||
label: '',
|
||||
}),
|
||||
}),
|
||||
});
|
79
config/ags/js/bar/main.js
Normal file
79
config/ags/js/bar/main.js
Normal file
|
@ -0,0 +1,79 @@
|
|||
const { Window, CenterBox, Box } = ags.Widget;
|
||||
|
||||
import { Separator } from '../misc/separator.js';
|
||||
import { CurrentWindow } from './current-window.js';
|
||||
import { Workspaces } from './workspaces.js';
|
||||
import { OskToggle } from './osk-toggle.js';
|
||||
import { TabletToggle } from './tablet-toggle.js';
|
||||
import { QsToggle } from './quick-settings.js';
|
||||
import { NotifButton } from './notif-button.js';
|
||||
import { Clock } from './clock.js';
|
||||
import { SysTray } from './systray.js';
|
||||
import { BatteryIndicator } from './battery.js';
|
||||
import { Brightness } from './brightness.js';
|
||||
import { AudioIndicator } from './audio.js';
|
||||
import { Gesture } from './gesture.js';
|
||||
|
||||
export const Bar = Window({
|
||||
name: 'bar',
|
||||
layer: 'overlay',
|
||||
anchor: 'top left right',
|
||||
exclusive: true,
|
||||
|
||||
child: Gesture({
|
||||
child: CenterBox({
|
||||
className: 'transparent',
|
||||
halign: 'fill',
|
||||
style: 'margin: 5px',
|
||||
vertical: false,
|
||||
|
||||
startWidget: Box({
|
||||
halign: 'start',
|
||||
children: [
|
||||
|
||||
OskToggle,
|
||||
|
||||
Separator(12),
|
||||
|
||||
TabletToggle,
|
||||
|
||||
Separator(12),
|
||||
|
||||
SysTray,
|
||||
|
||||
AudioIndicator,
|
||||
|
||||
Separator(12),
|
||||
|
||||
Brightness,
|
||||
|
||||
Separator(12),
|
||||
|
||||
Workspaces,
|
||||
|
||||
],
|
||||
}),
|
||||
|
||||
centerWidget: CurrentWindow,
|
||||
|
||||
endWidget: Box({
|
||||
halign: 'end',
|
||||
children: [
|
||||
BatteryIndicator,
|
||||
|
||||
Separator(12),
|
||||
|
||||
Clock,
|
||||
|
||||
Separator(12),
|
||||
|
||||
NotifButton,
|
||||
|
||||
Separator(12),
|
||||
|
||||
QsToggle,
|
||||
],
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
});
|
54
config/ags/js/bar/notif-button.js
Normal file
54
config/ags/js/bar/notif-button.js
Normal file
|
@ -0,0 +1,54 @@
|
|||
const { Box, Label, Icon } = ags.Widget;
|
||||
const { toggleWindow } = ags.App;
|
||||
const { Notifications } = ags.Service;
|
||||
|
||||
import { Separator } from '../misc/separator.js';
|
||||
import { EventBox } from '../misc/cursorbox.js';
|
||||
|
||||
export const NotifButton = EventBox({
|
||||
className: 'toggle-off',
|
||||
onPrimaryClickRelease: () => toggleWindow('notification-center'),
|
||||
connections: [
|
||||
[ags.App, (box, windowName, visible) => {
|
||||
if (windowName == 'notification-center') {
|
||||
box.toggleClassName('toggle-on', visible);
|
||||
}
|
||||
}],
|
||||
],
|
||||
child: Box({
|
||||
className: 'notif-panel',
|
||||
vertical: false,
|
||||
children: [
|
||||
Separator(28),
|
||||
|
||||
Icon({
|
||||
connections: [
|
||||
[Notifications, icon => {
|
||||
if (Notifications.dnd) {
|
||||
icon.icon = 'notification-disabled-symbolic'
|
||||
}
|
||||
else {
|
||||
if (Notifications.notifications.length > 0) {
|
||||
icon.icon = 'notification-new-symbolic'
|
||||
}
|
||||
else {
|
||||
icon.icon = 'notification-symbolic'
|
||||
}
|
||||
}
|
||||
}],
|
||||
],
|
||||
}),
|
||||
|
||||
Separator(8),
|
||||
|
||||
Label({
|
||||
connections: [
|
||||
[Notifications, label => {
|
||||
label.label = String(Notifications.notifications.length);
|
||||
}],
|
||||
],
|
||||
}),
|
||||
|
||||
],
|
||||
}),
|
||||
});
|
41
config/ags/js/bar/osk-toggle.js
Normal file
41
config/ags/js/bar/osk-toggle.js
Normal file
|
@ -0,0 +1,41 @@
|
|||
const { Box, Label } = ags.Widget;
|
||||
const { subprocess } = ags.Utils;
|
||||
const deflisten = subprocess;
|
||||
|
||||
import { EventBox } from '../misc/cursorbox.js';
|
||||
|
||||
deflisten(
|
||||
['bash', '-c', '$AGS_PATH/osk-toggle.sh getState'],
|
||||
(output) => {
|
||||
if (output == 'Running') {
|
||||
OskToggle.toggleClassName('toggle-on', true);
|
||||
} else {
|
||||
OskToggle.toggleClassName('toggle-on', false);
|
||||
}
|
||||
},
|
||||
);
|
||||
export const OskToggle = EventBox({
|
||||
className: 'toggle-off',
|
||||
onPrimaryClickRelease: function() {
|
||||
subprocess(
|
||||
['bash', '-c', '$AGS_PATH/osk-toggle.sh toggle'],
|
||||
(output) => {
|
||||
if (output == 'Running') {
|
||||
OskToggle.toggleClassName('toggle-on', false);
|
||||
} else {
|
||||
OskToggle.toggleClassName('toggle-on', true);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Box({
|
||||
className: 'osk-toggle',
|
||||
vertical: false,
|
||||
|
||||
children: [
|
||||
Label({
|
||||
label: " ",
|
||||
}),
|
||||
],
|
||||
}),
|
||||
});
|
23
config/ags/js/bar/quick-settings.js
Normal file
23
config/ags/js/bar/quick-settings.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
const { Box, Label } = ags.Widget;
|
||||
const { toggleWindow } = ags.App;
|
||||
|
||||
import { EventBox } from '../misc/cursorbox.js';
|
||||
|
||||
export const QsToggle = EventBox({
|
||||
className: 'toggle-off',
|
||||
onPrimaryClickRelease: () => toggleWindow('quick-settings'),
|
||||
connections: [
|
||||
[ags.App, (box, windowName, visible) => {
|
||||
if (windowName == 'quick-settings') {
|
||||
box.toggleClassName('toggle-on', visible);
|
||||
}
|
||||
}],
|
||||
],
|
||||
child: Box({
|
||||
className: 'quick-settings-toggle',
|
||||
vertical: false,
|
||||
child: Label({
|
||||
label: " ",
|
||||
}),
|
||||
}),
|
||||
});
|
57
config/ags/js/bar/systray.js
Normal file
57
config/ags/js/bar/systray.js
Normal file
|
@ -0,0 +1,57 @@
|
|||
const { SystemTray } = ags.Service;
|
||||
const { Box, Revealer, Icon, MenuItem } = ags.Widget;
|
||||
const { Gtk } = imports.gi;
|
||||
|
||||
import { Separator } from '../misc/separator.js';
|
||||
|
||||
const SysTrayItem = item => MenuItem({
|
||||
className: 'tray-item',
|
||||
child: Icon({
|
||||
size: 24,
|
||||
}),
|
||||
submenu: item.menu,
|
||||
connections: [[item, btn => {
|
||||
btn.child.icon = item.icon;
|
||||
btn.tooltipMarkup = item.tooltipMarkup;
|
||||
}]]
|
||||
});
|
||||
|
||||
export const SysTray = Revealer({
|
||||
transition: 'slide_right',
|
||||
connections: [[SystemTray, rev => {
|
||||
rev.revealChild = rev.child.children[0].get_children().length > 0;
|
||||
}]],
|
||||
child: Box({
|
||||
children: [
|
||||
ags.Widget({
|
||||
type: Gtk.MenuBar,
|
||||
className: 'sys-tray',
|
||||
properties: [
|
||||
['items', new Map()],
|
||||
['onAdded', (box, id) => {
|
||||
const item = SystemTray.getItem(id);
|
||||
if (box._items.has(id) || !item)
|
||||
return;
|
||||
|
||||
const widget = SysTrayItem(item);
|
||||
box._items.set(id, widget);
|
||||
box.add(widget);
|
||||
box.show_all();
|
||||
}],
|
||||
['onRemoved', (box, id) => {
|
||||
if (!box._items.has(id))
|
||||
return;
|
||||
|
||||
box._items.get(id).destroy();
|
||||
box._items.delete(id);
|
||||
}],
|
||||
],
|
||||
connections: [
|
||||
[SystemTray, (box, id) => box._onAdded(box, id), 'added'],
|
||||
[SystemTray, (box, id) => box._onRemoved(box, id), 'removed'],
|
||||
],
|
||||
}),
|
||||
Separator(12),
|
||||
],
|
||||
}),
|
||||
});
|
28
config/ags/js/bar/tablet-toggle.js
Normal file
28
config/ags/js/bar/tablet-toggle.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
const { Box, Label } = ags.Widget;
|
||||
const { subprocess } = ags.Utils;
|
||||
|
||||
import { EventBox } from '../misc/cursorbox.js';
|
||||
|
||||
export const TabletToggle = EventBox({
|
||||
className: 'toggle-off',
|
||||
onPrimaryClickRelease: function() {
|
||||
subprocess(
|
||||
['bash', '-c', '$AGS_PATH/tablet-toggle.sh toggle'],
|
||||
(output) => {
|
||||
print(output)
|
||||
if (output == 'Tablet') {
|
||||
TabletToggle.toggleClassName('toggle-on', true);
|
||||
} else {
|
||||
TabletToggle.toggleClassName('toggle-on', false);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Box({
|
||||
className: 'tablet-toggle',
|
||||
vertical: false,
|
||||
child: Label({
|
||||
label: " ",
|
||||
}),
|
||||
}),
|
||||
});
|
70
config/ags/js/bar/workspaces.js
Normal file
70
config/ags/js/bar/workspaces.js
Normal file
|
@ -0,0 +1,70 @@
|
|||
const { Hyprland, Applications } = ags.Service;
|
||||
const { execAsync } = ags.Utils;
|
||||
const { Box, Button, Label, Revealer } = ags.Widget;
|
||||
|
||||
import { EventBox } from '../misc/cursorbox.js';
|
||||
|
||||
const Workspace = ({ i } = {}) =>
|
||||
Revealer({
|
||||
transition: "slide_right",
|
||||
properties: [
|
||||
['id', i],
|
||||
],
|
||||
child: EventBox({
|
||||
tooltipText: `${i}`,
|
||||
onPrimaryClickRelease: () => execAsync(`hyprctl dispatch workspace ${i}`).catch(print),
|
||||
child: Box({
|
||||
className: 'button',
|
||||
child: Label(`${i}`),
|
||||
connections: [
|
||||
[Hyprland, btn => {
|
||||
const occupied = Hyprland.getWorkspace(i)?.windows > 0;
|
||||
btn.toggleClassName('active', Hyprland.active.workspace.id === i);
|
||||
btn.toggleClassName('occupied', occupied);
|
||||
btn.toggleClassName('empty', !occupied);
|
||||
}]
|
||||
],
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
export const Workspaces = Box({
|
||||
className: 'workspaces',
|
||||
children: [EventBox({
|
||||
child: Box({
|
||||
properties: [
|
||||
['workspaces'],
|
||||
|
||||
['refresh', box => {
|
||||
box.children.forEach(rev => rev.reveal_child = false);
|
||||
box._workspaces.forEach(ws => {
|
||||
ws.revealChild = true;
|
||||
});
|
||||
}],
|
||||
|
||||
['updateWs', box => {
|
||||
Hyprland.workspaces.forEach(ws => {
|
||||
let currentWs = box.children.find(ch => ch._id == ws.id);
|
||||
if (!currentWs && ws.id > 0) {
|
||||
box.add(Workspace({ i: ws.id}));
|
||||
}
|
||||
});
|
||||
box.show_all();
|
||||
|
||||
// Make sure the order is correct
|
||||
box._workspaces.forEach((workspace, i) => {
|
||||
workspace.get_parent().reorder_child(workspace, i);
|
||||
});
|
||||
}],
|
||||
],
|
||||
connections: [[Hyprland, box => {
|
||||
box._workspaces = box.children.filter(ch => {
|
||||
return Hyprland.workspaces.find(ws => ws.id == ch._id)
|
||||
}).sort((a, b) => a._id - b._id);
|
||||
|
||||
box._updateWs(box);
|
||||
box._refresh(box);
|
||||
}]],
|
||||
}),
|
||||
})],
|
||||
});
|
88
config/ags/js/date.js
Normal file
88
config/ags/js/date.js
Normal file
|
@ -0,0 +1,88 @@
|
|||
const { Box, Label, Window } = ags.Widget;
|
||||
const { Gtk } = imports.gi;
|
||||
const { DateTime } = imports.gi.GLib;
|
||||
|
||||
import { PopUp } from './misc/popup.js';
|
||||
|
||||
const Divider = () => Box({
|
||||
className: 'divider',
|
||||
vertical: true,
|
||||
});
|
||||
|
||||
const Time = () => Box({
|
||||
className: 'timebox',
|
||||
vertical: true,
|
||||
children: [
|
||||
|
||||
Box({
|
||||
className: 'time-container',
|
||||
halign: 'center',
|
||||
valign: 'center',
|
||||
children: [
|
||||
|
||||
Label({
|
||||
className: 'content',
|
||||
label: 'hour',
|
||||
connections: [[1000, label => {
|
||||
label.label = DateTime.new_now_local().format('%H');
|
||||
}]],
|
||||
}),
|
||||
|
||||
Divider(),
|
||||
|
||||
Label({
|
||||
className: 'content',
|
||||
label: 'minute',
|
||||
connections: [[1000, label => {
|
||||
label.label = DateTime.new_now_local().format('%M');
|
||||
}]],
|
||||
}),
|
||||
|
||||
],
|
||||
}),
|
||||
|
||||
Box({
|
||||
className: 'date-container',
|
||||
halign: 'center',
|
||||
child: Label({
|
||||
style: 'font-size: 20px',
|
||||
label: 'complete date',
|
||||
connections: [[1000, label => {
|
||||
var time = DateTime.new_now_local();
|
||||
label.label = time.format("%A, %B ") + time.get_day_of_month() + time.format(", %Y");
|
||||
}]],
|
||||
}),
|
||||
}),
|
||||
|
||||
],
|
||||
});
|
||||
|
||||
const CalendarWidget = () => Box({
|
||||
className: 'cal-box',
|
||||
child: ags.Widget({
|
||||
type: Gtk.Calendar,
|
||||
showDayNames: true,
|
||||
showHeading: true,
|
||||
className: 'cal',
|
||||
connections: [/* */]
|
||||
}),
|
||||
});
|
||||
|
||||
export const Calendar = Window({
|
||||
name: 'calendar',
|
||||
layer: 'overlay',
|
||||
popup: true,
|
||||
anchor: 'top right',
|
||||
margin: [ 8, 182, 0, 0],
|
||||
child: PopUp({
|
||||
name: 'calendar',
|
||||
child: Box({
|
||||
className: 'date',
|
||||
vertical: true,
|
||||
children: [
|
||||
Time(),
|
||||
CalendarWidget(),
|
||||
],
|
||||
}),
|
||||
}),
|
||||
});
|
82
config/ags/js/media-player/gesture.js
Normal file
82
config/ags/js/media-player/gesture.js
Normal file
|
@ -0,0 +1,82 @@
|
|||
const { Box, Overlay, EventBox } = ags.Widget;
|
||||
const { Gtk } = imports.gi;
|
||||
|
||||
const MAX_OFFSET = 200;
|
||||
const OFFSCREEN = 500;
|
||||
const TRANSITION = 'transition: margin 0.5s ease, opacity 3s ease;';
|
||||
|
||||
export default ({ properties, connections, params } = {}) => {
|
||||
let widget = EventBox();
|
||||
|
||||
let gesture = Gtk.GestureDrag.new(widget)
|
||||
|
||||
widget.child = Overlay({
|
||||
...params,
|
||||
properties: [
|
||||
...properties,
|
||||
['dragging', false],
|
||||
],
|
||||
child: Box({className: 'player'}),
|
||||
connections: [
|
||||
...connections,
|
||||
|
||||
[gesture, overlay => {
|
||||
if (overlay.overlays.length <= 1)
|
||||
return;
|
||||
|
||||
overlay._dragging = true;
|
||||
const offset = gesture.get_offset()[1];
|
||||
|
||||
let playerBox = overlay.get_children().at(-1);
|
||||
if (offset >= 0) {
|
||||
playerBox.setStyle(`margin-left: ${offset}px;
|
||||
margin-right: -${offset}px;
|
||||
${playerBox._bgStyle}`);
|
||||
}
|
||||
else {
|
||||
let newOffset = Math.abs(offset);
|
||||
playerBox.setStyle(`margin-left: -${newOffset}px;
|
||||
margin-right: ${newOffset}px;
|
||||
${playerBox._bgStyle}`);
|
||||
}
|
||||
overlay._selected = playerBox;
|
||||
}, 'drag-update'],
|
||||
|
||||
[gesture, overlay => {
|
||||
if (overlay.overlays.length <= 1)
|
||||
return;
|
||||
|
||||
overlay._dragging = false;
|
||||
const offset = gesture.get_offset()[1];
|
||||
|
||||
let playerBox = overlay.get_children().at(-1);
|
||||
|
||||
if (Math.abs(offset) > MAX_OFFSET) {
|
||||
if (offset >= 0) {
|
||||
playerBox.setStyle(`${TRANSITION}
|
||||
margin-left: ${OFFSCREEN}px;
|
||||
margin-right: -${OFFSCREEN}px;
|
||||
opacity: 0;
|
||||
${playerBox._bgStyle}`);
|
||||
}
|
||||
else {
|
||||
playerBox.setStyle(`${TRANSITION}
|
||||
margin-left: -${OFFSCREEN}px;
|
||||
margin-right: ${OFFSCREEN}px;
|
||||
opacity: 0;
|
||||
${playerBox._bgStyle}`);
|
||||
}
|
||||
setTimeout(() => {
|
||||
overlay.reorder_overlay(playerBox, 0);
|
||||
playerBox.setStyle(playerBox._bgStyle);
|
||||
overlay._selected = overlay.get_children().at(-1);
|
||||
}, 500);
|
||||
}
|
||||
else
|
||||
playerBox.setStyle(`${TRANSITION} ${playerBox._bgStyle}`);
|
||||
|
||||
}, 'drag-end'],
|
||||
],
|
||||
});
|
||||
return widget;
|
||||
};
|
345
config/ags/js/media-player/mpris.js
Normal file
345
config/ags/js/media-player/mpris.js
Normal file
|
@ -0,0 +1,345 @@
|
|||
const { execAsync, lookUpIcon } = ags.Utils;
|
||||
const { Mpris } = ags.Service;
|
||||
const { Button, Icon, Label, Stack, Slider, CenterBox, Box } = ags.Widget;
|
||||
const { Gdk } = imports.gi;
|
||||
const display = Gdk.Display.get_default();
|
||||
|
||||
import { EventBox } from '../misc/cursorbox.js';
|
||||
import { Separator } from '../misc/separator.js';
|
||||
|
||||
const icons = {
|
||||
mpris: {
|
||||
fallback: 'audio-x-generic-symbolic',
|
||||
shuffle: {
|
||||
enabled: '',
|
||||
disabled: '',
|
||||
},
|
||||
loop: {
|
||||
none: '',
|
||||
track: '',
|
||||
playlist: '',
|
||||
},
|
||||
playing: ' ',
|
||||
paused: ' ',
|
||||
stopped: ' ',
|
||||
prev: '',
|
||||
next: '',
|
||||
},
|
||||
}
|
||||
|
||||
export const CoverArt = (player, params) => CenterBox({
|
||||
...params,
|
||||
vertical: true,
|
||||
properties: [['bgStyle', '']],
|
||||
connections: [
|
||||
[player, box => {
|
||||
execAsync(['bash', '-c', `[[ -f "${player.coverPath}" ]] && coloryou "${player.coverPath}"`])
|
||||
.then(out => {
|
||||
if (!Mpris.players.find(p => player === p))
|
||||
return;
|
||||
|
||||
player.colors.value = JSON.parse(out);
|
||||
|
||||
box._bgStyle = `background: radial-gradient(circle,
|
||||
rgba(0, 0, 0, 0.4) 30%,
|
||||
${player.colors.value.imageAccent}),
|
||||
url("${player.coverPath}");
|
||||
background-size: cover;
|
||||
background-position: center;`;
|
||||
if (!box.get_parent()._dragging)
|
||||
box.setStyle(box._bgStyle);
|
||||
}).catch(err => { if (err !== "") print(err) });
|
||||
}],
|
||||
],
|
||||
});
|
||||
|
||||
export const TitleLabel = (player, params) => Label({
|
||||
...params,
|
||||
xalign: 0,
|
||||
maxWidthChars: 40,
|
||||
truncate: 'end',
|
||||
justification: 'left',
|
||||
className: 'title',
|
||||
binds: [['label', player, 'trackTitle']],
|
||||
});
|
||||
|
||||
export const ArtistLabel = (player, params) => Label({
|
||||
...params,
|
||||
xalign: 0,
|
||||
maxWidthChars: 40,
|
||||
truncate: 'end',
|
||||
justification: 'left',
|
||||
className: 'artist',
|
||||
connections: [[player, label => {
|
||||
label.label = player.trackArtists.join(', ') || '';
|
||||
}]],
|
||||
});
|
||||
|
||||
export const PlayerIcon = (player, { symbolic = true, ...params } = {}) => {
|
||||
let MainIcon = Icon({
|
||||
...params,
|
||||
className: 'player-icon',
|
||||
size: 32,
|
||||
tooltipText: player.identity || '',
|
||||
connections: [
|
||||
[player, icon => {
|
||||
const name = `${player.entry}${symbolic ? '-symbolic' : ''}`;
|
||||
lookUpIcon(name) ? icon.icon = name
|
||||
: icon.icon = icons.mpris.fallback;
|
||||
}],
|
||||
],
|
||||
});
|
||||
|
||||
return Box({
|
||||
connections: [
|
||||
[Mpris, box => {
|
||||
let overlays = box.get_parent().get_parent().get_parent().overlays;
|
||||
let player = overlays.find(overlay => overlay === box.get_parent().get_parent());
|
||||
let index = overlays.indexOf(player)
|
||||
|
||||
let children = [];
|
||||
for (let i = 0; i < overlays.length; ++i) {
|
||||
if (i === index) {
|
||||
children.push(MainIcon);
|
||||
children.push(Separator(2));
|
||||
}
|
||||
else {
|
||||
children.push(Box({ className: 'position-indicator' }));
|
||||
children.push(Separator(2));
|
||||
}
|
||||
}
|
||||
box.children = children;
|
||||
}],
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
export const PositionSlider = (player, params) => EventBox({
|
||||
child: Slider({
|
||||
...params,
|
||||
className: 'position-slider',
|
||||
hexpand: true,
|
||||
drawValue: false,
|
||||
onChange: ({ value }) => {
|
||||
player.position = player.length * value;
|
||||
},
|
||||
properties: [
|
||||
['update', slider => {
|
||||
if (slider.dragging) {
|
||||
slider.get_parent().window.set_cursor(Gdk.Cursor.new_from_name(display, 'grabbing'));
|
||||
}
|
||||
else {
|
||||
if (slider.get_parent() && slider.get_parent().window) {
|
||||
slider.get_parent().window.set_cursor(Gdk.Cursor.new_from_name(display, 'pointer'));
|
||||
}
|
||||
|
||||
slider.sensitive = player.length > 0;
|
||||
if (player.length > 0) {
|
||||
slider.value = player.position / player.length;
|
||||
}
|
||||
}
|
||||
}],
|
||||
],
|
||||
connections: [
|
||||
[player, s => s._update(s), 'position'],
|
||||
[1000, s => s._update(s)],
|
||||
[player.colors, s => {
|
||||
if (player.colors.value)
|
||||
s.setCss(`highlight { background-color: ${player.colors.value.buttonAccent}; }
|
||||
slider { background-color: ${player.colors.value.buttonAccent}; }
|
||||
slider:hover { background-color: ${player.colors.value.hoverAccent}; }
|
||||
trough { background-color: ${player.colors.value.buttonText}; }`);
|
||||
}],
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
function lengthStr(length) {
|
||||
const min = Math.floor(length / 60);
|
||||
const sec0 = Math.floor(length % 60) < 10 ? '0' : '';
|
||||
const sec = Math.floor(length % 60);
|
||||
return `${min}:${sec0}${sec}`;
|
||||
}
|
||||
|
||||
export const PositionLabel = player => Label({
|
||||
properties: [['update', label => {
|
||||
player.length > 0 ? label.label = lengthStr(player.position)
|
||||
: label.visible = !!player;
|
||||
}]],
|
||||
connections: [
|
||||
[player, l => l._update(l), 'position'],
|
||||
[1000, l => l._update(l)],
|
||||
],
|
||||
});
|
||||
|
||||
export const LengthLabel = player => Label({
|
||||
connections: [[player, label => {
|
||||
player.length > 0 ? label.label = lengthStr(player.length)
|
||||
: label.visible = !!player;
|
||||
}]],
|
||||
});
|
||||
|
||||
export const Slash = player => Label({
|
||||
label: '/',
|
||||
connections: [[player, label => {
|
||||
label.visible = player.length > 0;
|
||||
}]],
|
||||
});
|
||||
|
||||
// TODO: use label instead of stack to fix UI issues
|
||||
const PlayerButton = ({ player, items, onClick, prop }) => Button({
|
||||
child: Stack({ items }),
|
||||
onPrimaryClickRelease: () => player[onClick](),
|
||||
properties: [['hovered', false]],
|
||||
onHover: box => {
|
||||
box._hovered = true;
|
||||
if (! box.child.sensitive || ! box.sensitive) {
|
||||
box.window.set_cursor(Gdk.Cursor.new_from_name(display, 'not-allowed'));
|
||||
}
|
||||
else {
|
||||
box.window.set_cursor(Gdk.Cursor.new_from_name(display, 'pointer'));
|
||||
}
|
||||
|
||||
if (prop == 'playBackStatus') {
|
||||
items.forEach(item => {
|
||||
item[1].setStyle(`background-color: ${player.colors.value.hoverAccent};
|
||||
color: ${player.colors.value.buttonText};
|
||||
min-height: 40px; min-width: 36px;
|
||||
margin-bottom: 1px; margin-right: 1px;`);
|
||||
});
|
||||
}
|
||||
},
|
||||
onHoverLost: box => {
|
||||
box._hovered = false;
|
||||
box.window.set_cursor(null);
|
||||
if (prop == 'playBackStatus') {
|
||||
items.forEach(item => {
|
||||
item[1].setStyle(`background-color: ${player.colors.value.buttonAccent};
|
||||
color: ${player.colors.value.buttonText};
|
||||
min-height: 42px; min-width: 38px;`);
|
||||
});
|
||||
}
|
||||
},
|
||||
connections: [
|
||||
[player, button => {
|
||||
button.child.shown = `${player[prop]}`;
|
||||
}],
|
||||
|
||||
[player.colors, button => {
|
||||
if (!Mpris.players.find(p => player === p))
|
||||
return;
|
||||
|
||||
if (player.colors.value) {
|
||||
if (prop == 'playBackStatus') {
|
||||
if (button._hovered) {
|
||||
items.forEach(item => {
|
||||
item[1].setStyle(`background-color: ${player.colors.value.hoverAccent};
|
||||
color: ${player.colors.value.buttonText};
|
||||
min-height: 40px; min-width: 36px;
|
||||
margin-bottom: 1px; margin-right: 1px;`);
|
||||
});
|
||||
}
|
||||
else {
|
||||
items.forEach(item => {
|
||||
item[1].setStyle(`background-color: ${player.colors.value.buttonAccent};
|
||||
color: ${player.colors.value.buttonText};
|
||||
min-height: 42px; min-width: 38px;`);
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
button.setCss(`* { color: ${player.colors.value.buttonAccent}; }
|
||||
*:hover { color: ${player.colors.value.hoverAccent}; }`);
|
||||
}
|
||||
}
|
||||
}],
|
||||
],
|
||||
});
|
||||
|
||||
export const ShuffleButton = player => PlayerButton({
|
||||
player,
|
||||
items: [
|
||||
['true', Label({
|
||||
className: 'shuffle enabled',
|
||||
label: icons.mpris.shuffle.enabled,
|
||||
})],
|
||||
['false', Label({
|
||||
className: 'shuffle disabled',
|
||||
label: icons.mpris.shuffle.disabled,
|
||||
})],
|
||||
],
|
||||
onClick: 'shuffle',
|
||||
prop: 'shuffleStatus',
|
||||
});
|
||||
|
||||
export const LoopButton = player => PlayerButton({
|
||||
player,
|
||||
items: [
|
||||
['None', Label({
|
||||
className: 'loop none',
|
||||
label: icons.mpris.loop.none,
|
||||
})],
|
||||
['Track', Label({
|
||||
className: 'loop track',
|
||||
label: icons.mpris.loop.track,
|
||||
})],
|
||||
['Playlist', Label({
|
||||
className: 'loop playlist',
|
||||
label: icons.mpris.loop.playlist,
|
||||
})],
|
||||
],
|
||||
onClick: 'loop',
|
||||
prop: 'loopStatus',
|
||||
});
|
||||
|
||||
export const PlayPauseButton = player => PlayerButton({
|
||||
player,
|
||||
items: [
|
||||
['Playing', Label({
|
||||
className: 'pausebutton playing',
|
||||
label: icons.mpris.playing,
|
||||
})],
|
||||
['Paused', Label({
|
||||
className: 'pausebutton paused',
|
||||
label: icons.mpris.paused,
|
||||
})],
|
||||
['Stopped', Label({
|
||||
className: 'pausebutton stopped paused',
|
||||
label: icons.mpris.stopped,
|
||||
})],
|
||||
],
|
||||
onClick: 'playPause',
|
||||
prop: 'playBackStatus',
|
||||
});
|
||||
|
||||
export const PreviousButton = player => PlayerButton({
|
||||
player,
|
||||
items: [
|
||||
['true', Label({
|
||||
className: 'previous',
|
||||
label: icons.mpris.prev,
|
||||
})],
|
||||
['false', Label({
|
||||
className: 'previous',
|
||||
label: icons.mpris.prev,
|
||||
})],
|
||||
],
|
||||
onClick: 'previous',
|
||||
prop: 'canGoPrev',
|
||||
});
|
||||
|
||||
export const NextButton = player => PlayerButton({
|
||||
player,
|
||||
items: [
|
||||
['true', Label({
|
||||
className: 'next',
|
||||
label: icons.mpris.next,
|
||||
})],
|
||||
['false', Label({
|
||||
className: 'next',
|
||||
label: icons.mpris.next,
|
||||
})],
|
||||
],
|
||||
onClick: 'next',
|
||||
prop: 'canGoNext',
|
||||
});
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue