Initial Push.
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
*.swp
|
||||||
|
*.kate-swp
|
||||||
|
result/*
|
||||||
|
result
|
||||||
145
configuration.nix
Normal file
145
configuration.nix
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
# Edit this configuration file to define what should be installed on
|
||||||
|
# your system. Help is available in the configuration.nix(5) man page
|
||||||
|
# and in the NixOS manual (accessible by running ‘nixos-help’).
|
||||||
|
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports =
|
||||||
|
[ # Include the results of the hardware scan.
|
||||||
|
./hardware-configuration.nix
|
||||||
|
];
|
||||||
|
nix.settings.experimental-features = [ "nix-command" "flakes" ];
|
||||||
|
# Bootloader.
|
||||||
|
boot.loader.systemd-boot.enable = true;
|
||||||
|
boot.loader.efi.canTouchEfiVariables = true;
|
||||||
|
boot.kernelModules = [ "fuse" "coretemp" "cifs" ];
|
||||||
|
|
||||||
|
networking.hostName = "xps13"; # Define your hostname.
|
||||||
|
networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
|
||||||
|
# networking.networkmanager.enable = true;
|
||||||
|
networking.wireless.networks = {
|
||||||
|
MyLocalTech = {
|
||||||
|
pskRaw = "ac1030d721d26deb2c7db10073dfac73244e9621f4462e3e568017da03201e0e";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
# Set your time zone.
|
||||||
|
time.timeZone = "America/New_York";
|
||||||
|
|
||||||
|
# Select internationalisation properties.
|
||||||
|
i18n.defaultLocale = "en_US.UTF-8";
|
||||||
|
|
||||||
|
i18n.extraLocaleSettings = {
|
||||||
|
LC_ADDRESS = "en_US.UTF-8";
|
||||||
|
LC_IDENTIFICATION = "en_US.UTF-8";
|
||||||
|
LC_MEASUREMENT = "en_US.UTF-8";
|
||||||
|
LC_MONETARY = "en_US.UTF-8";
|
||||||
|
LC_NAME = "en_US.UTF-8";
|
||||||
|
LC_NUMERIC = "en_US.UTF-8";
|
||||||
|
LC_PAPER = "en_US.UTF-8";
|
||||||
|
LC_TELEPHONE = "en_US.UTF-8";
|
||||||
|
LC_TIME = "en_US.UTF-8";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Enable the X11 windowing system.
|
||||||
|
# You can disable this if you're only using the Wayland session.
|
||||||
|
services.xserver.enable = true;
|
||||||
|
|
||||||
|
# Enable the KDE Plasma Desktop Environment.
|
||||||
|
services.displayManager.sddm.enable = true;
|
||||||
|
services.desktopManager.plasma6.enable = true;
|
||||||
|
|
||||||
|
# Configure keymap in X11
|
||||||
|
services.xserver.xkb = {
|
||||||
|
layout = "us";
|
||||||
|
variant = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Enable CUPS to print documents.
|
||||||
|
services.printing.enable = true;
|
||||||
|
|
||||||
|
# Enable sound with pipewire.
|
||||||
|
services.pulseaudio.enable = false;
|
||||||
|
security.rtkit.enable = true;
|
||||||
|
services.pipewire = {
|
||||||
|
enable = true;
|
||||||
|
alsa.enable = true;
|
||||||
|
alsa.support32Bit = true;
|
||||||
|
pulse.enable = true;
|
||||||
|
# If you want to use JACK applications, uncomment this
|
||||||
|
jack.enable = true;
|
||||||
|
|
||||||
|
# use the example session manager (no others are packaged yet so this is enabled by default,
|
||||||
|
# no need to redefine it in your config for now)
|
||||||
|
#media-session.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Enable touchpad support (enabled default in most desktopManager).
|
||||||
|
services.libinput.enable = true;
|
||||||
|
fonts.packages = with pkgs; [
|
||||||
|
nerd-fonts.fira-code
|
||||||
|
nerd-fonts.space-mono
|
||||||
|
nerd-fonts.sauce-code-pro
|
||||||
|
nerd-fonts.monofur
|
||||||
|
];
|
||||||
|
|
||||||
|
# Define a user account. Don't forget to set a password with ‘passwd’.
|
||||||
|
users.users.th3r00t = {
|
||||||
|
isNormalUser = true;
|
||||||
|
description = "Mike 'th3r00t' Young";
|
||||||
|
extraGroups = [ "networkmanager" "wheel" ];
|
||||||
|
packages = with pkgs; [
|
||||||
|
kdePackages.kate
|
||||||
|
# thunderbird
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Enable automatic login for the user.
|
||||||
|
services.displayManager.autoLogin.enable = true;
|
||||||
|
services.displayManager.autoLogin.user = "th3r00t";
|
||||||
|
|
||||||
|
# Install firefox.
|
||||||
|
programs.firefox.enable = true;
|
||||||
|
|
||||||
|
# Allow unfree packages
|
||||||
|
nixpkgs.config.allowUnfree = true;
|
||||||
|
|
||||||
|
# List packages installed in system profile. To search, run:
|
||||||
|
# $ nix search wget
|
||||||
|
environment.variables.EDITOR = "vim";
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
# vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
|
||||||
|
# wget
|
||||||
|
git
|
||||||
|
vim
|
||||||
|
curl
|
||||||
|
];
|
||||||
|
|
||||||
|
# Some programs need SUID wrappers, can be configured further or are
|
||||||
|
# started in user sessions.
|
||||||
|
programs.mtr.enable = true;
|
||||||
|
programs.gnupg.agent = {
|
||||||
|
enable = true;
|
||||||
|
enableSSHSupport = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# List services that you want to enable:
|
||||||
|
|
||||||
|
# Enable the OpenSSH daemon.
|
||||||
|
services.openssh.enable = true;
|
||||||
|
|
||||||
|
# Open ports in the firewall.
|
||||||
|
networking.firewall.allowedTCPPorts = [ 21 22 80 443 8080 ];
|
||||||
|
networking.firewall.allowedUDPPorts = [ 21 22 80 443 8080 ];
|
||||||
|
# Or disable the firewall altogether.
|
||||||
|
# networking.firewall.enable = false;
|
||||||
|
|
||||||
|
# This value determines the NixOS release from which the default
|
||||||
|
# settings for stateful data, like file locations and database versions
|
||||||
|
# on your system were taken. It‘s perfectly fine and recommended to leave
|
||||||
|
# this value at the release version of the first install of this system.
|
||||||
|
# Before changing this value read the documentation for this option
|
||||||
|
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
|
||||||
|
system.stateVersion = "25.05"; # Did you read the comment?
|
||||||
|
|
||||||
|
}
|
||||||
268
flake.lock
generated
Normal file
268
flake.lock
generated
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-compat": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1747046372,
|
||||||
|
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-compat_2": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1747046372,
|
||||||
|
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-parts": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs-lib": [
|
||||||
|
"neovim-nightly-overlay",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1754487366,
|
||||||
|
"narHash": "sha256-pHYj8gUBapuUzKV/kN/tR3Zvqc7o6gdFB9XKXIp1SQ8=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"rev": "af66ad14b28a127c5c0f3bbb298218fc63528a18",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-parts_2": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs-lib": [
|
||||||
|
"neovim-nightly-overlay",
|
||||||
|
"hercules-ci-effects",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1751413152,
|
||||||
|
"narHash": "sha256-Tyw1RjYEsp5scoigs1384gIg6e0GoBVjms4aXFfRssQ=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"rev": "77826244401ea9de6e3bac47c2db46005e1f30b5",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "flake-parts",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"git-hooks": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-compat": "flake-compat_2",
|
||||||
|
"gitignore": "gitignore",
|
||||||
|
"nixpkgs": [
|
||||||
|
"neovim-nightly-overlay",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1754416808,
|
||||||
|
"narHash": "sha256-c6yg0EQ9xVESx6HGDOCMcyRSjaTpNJP10ef+6fRcofA=",
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "git-hooks.nix",
|
||||||
|
"rev": "9c52372878df6911f9afc1e2a1391f55e4dfc864",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "git-hooks.nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gitignore": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"neovim-nightly-overlay",
|
||||||
|
"git-hooks",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1709087332,
|
||||||
|
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "gitignore.nix",
|
||||||
|
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "gitignore.nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"hercules-ci-effects": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-parts": "flake-parts_2",
|
||||||
|
"nixpkgs": [
|
||||||
|
"neovim-nightly-overlay",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1752595130,
|
||||||
|
"narHash": "sha256-CNBgr4OZSuklGtNOa9CnTNo9+Xceqn/EDAC1Tc43fH8=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "hercules-ci-effects",
|
||||||
|
"rev": "5f2e09654b2e70ba643e41609d9f9b6640f22113",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "hercules-ci-effects",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"home-manager": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1753592768,
|
||||||
|
"narHash": "sha256-oV695RvbAE4+R9pcsT9shmp6zE/+IZe6evHWX63f2Qg=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "home-manager",
|
||||||
|
"rev": "fc3add429f21450359369af74c2375cb34a2d204",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"ref": "release-25.05",
|
||||||
|
"repo": "home-manager",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"neovim-nightly-overlay": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-compat": "flake-compat",
|
||||||
|
"flake-parts": "flake-parts",
|
||||||
|
"git-hooks": "git-hooks",
|
||||||
|
"hercules-ci-effects": "hercules-ci-effects",
|
||||||
|
"neovim-src": "neovim-src",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"treefmt-nix": "treefmt-nix"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1755248222,
|
||||||
|
"narHash": "sha256-jFchbJjsVUF8kKlLHRrucG23T2iu+920PwWFMfvtksE=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "neovim-nightly-overlay",
|
||||||
|
"rev": "73fca33ad4ddc8fe41192e23dae9af0544798653",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "neovim-nightly-overlay",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"neovim-src": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1755213444,
|
||||||
|
"narHash": "sha256-phbfQOUazngOSVscRUPZclPk0Cn+G4XHodbtef9ZT8M=",
|
||||||
|
"owner": "neovim",
|
||||||
|
"repo": "neovim",
|
||||||
|
"rev": "7afcfb6c9ac53cb4192974934d6cdc360f4bebc7",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "neovim",
|
||||||
|
"repo": "neovim",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1755113249,
|
||||||
|
"narHash": "sha256-/bIVS2iP5mixEQWsaiiJ7EGLtk5Id9OehWbmTbzN6kE=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "e9e0d35e5f735bf3d1e96815272f46fe7083232c",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixpkgs-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1755078291,
|
||||||
|
"narHash": "sha256-Hu/gTDoi4uy6TAKISPHQusSMy8U6xUbLSDjKBYdhDIY=",
|
||||||
|
"owner": "NixOs",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "3385ca0cd7e14c1a1eb80401fe011705ff012323",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOs",
|
||||||
|
"ref": "nixos-25.05",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"home-manager": "home-manager",
|
||||||
|
"neovim-nightly-overlay": "neovim-nightly-overlay",
|
||||||
|
"nixpkgs": "nixpkgs_2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"treefmt-nix": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"neovim-nightly-overlay",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1754847726,
|
||||||
|
"narHash": "sha256-2vX8QjO5lRsDbNYvN9hVHXLU6oMl+V/PsmIiJREG4rE=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "treefmt-nix",
|
||||||
|
"rev": "7d81f6fb2e19bf84f1c65135d1060d829fae2408",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "treefmt-nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
38
flake.nix
Normal file
38
flake.nix
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
description = "System Flake";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOs/nixpkgs/nixos-25.05";
|
||||||
|
home-manager = {
|
||||||
|
url = "github:nix-community/home-manager/release-25.05";
|
||||||
|
# The `follows` keyword in inputs is used for inheritance.
|
||||||
|
# Here, `inputs.nixpkgs` of home-manager is kept consistent with
|
||||||
|
# the `inputs.nixpkgs` of the current flake,
|
||||||
|
# to avoid problems caused by different versions of nixpkgs.
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
neovim-nightly-overlay.url = "github:nix-community/neovim-nightly-overlay";
|
||||||
|
};
|
||||||
|
outputs = { self, nixpkgs, home-manager, ... }@inputs:
|
||||||
|
let
|
||||||
|
overlays = [
|
||||||
|
inputs.neovim-nightly-overlay.overlays.default
|
||||||
|
];
|
||||||
|
in {
|
||||||
|
nixosConfigurations.xps13 = nixpkgs.lib.nixosSystem {
|
||||||
|
system = "x86_64-linux";
|
||||||
|
specialArgs = { inherit overlays; };
|
||||||
|
modules = [
|
||||||
|
{ nixpkgs.overlays = overlays; }
|
||||||
|
./configuration.nix
|
||||||
|
home-manager.nixosModules.home-manager {
|
||||||
|
# home-manager.useGlobalPkgs = true;
|
||||||
|
home-manager.useUserPackages = true;
|
||||||
|
home-manager.sharedModules = [ {nixpkgs.overlays = overlays;} ];
|
||||||
|
home-manager.users.th3r00t = import ./home.nix;
|
||||||
|
# Optionally, use home-manager.extraSpecialArgs to pass arguments to home.nix
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
41
hardware-configuration.nix
Normal file
41
hardware-configuration.nix
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||||
|
# and may be overwritten by future invocations. Please make changes
|
||||||
|
# to /etc/nixos/configuration.nix instead.
|
||||||
|
{ config, lib, pkgs, modulesPath, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports =
|
||||||
|
[ (modulesPath + "/installer/scan/not-detected.nix")
|
||||||
|
];
|
||||||
|
|
||||||
|
boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "usb_storage" "sd_mod" "rtsx_pci_sdmmc" ];
|
||||||
|
boot.initrd.kernelModules = [ ];
|
||||||
|
boot.kernelModules = [ "kvm-intel" ];
|
||||||
|
boot.extraModulePackages = [ ];
|
||||||
|
|
||||||
|
fileSystems."/" =
|
||||||
|
{ device = "/dev/disk/by-uuid/c888d639-8af5-44c9-8692-24756792a960";
|
||||||
|
fsType = "ext4";
|
||||||
|
};
|
||||||
|
|
||||||
|
boot.initrd.luks.devices."luks-dd4f8026-08be-4db0-abca-b92e71afd3f7".device = "/dev/disk/by-uuid/dd4f8026-08be-4db0-abca-b92e71afd3f7";
|
||||||
|
|
||||||
|
fileSystems."/boot" =
|
||||||
|
{ device = "/dev/disk/by-uuid/FF76-573E";
|
||||||
|
fsType = "vfat";
|
||||||
|
options = [ "fmask=0077" "dmask=0077" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
swapDevices = [ ];
|
||||||
|
|
||||||
|
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
|
||||||
|
# (the default) this is the recommended approach. When using systemd-networkd it's
|
||||||
|
# still possible to use this option, but it's recommended to use it in conjunction
|
||||||
|
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
|
||||||
|
networking.useDHCP = lib.mkDefault true;
|
||||||
|
# networking.interfaces.enp57s0u1u2.useDHCP = lib.mkDefault true;
|
||||||
|
# networking.interfaces.wlp2s0.useDHCP = lib.mkDefault true;
|
||||||
|
|
||||||
|
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||||
|
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||||
|
}
|
||||||
308
home.nix
Normal file
308
home.nix
Normal file
@@ -0,0 +1,308 @@
|
|||||||
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
home.username = "th3r00t";
|
||||||
|
home.homeDirectory = "/home/th3r00t";
|
||||||
|
home.file.".local/usr/bin" = {
|
||||||
|
source = ./home/.local/usr/bin;
|
||||||
|
recursive = true;
|
||||||
|
executable = true;
|
||||||
|
};
|
||||||
|
home.file.".local/usr/lib/blightmud" = {
|
||||||
|
source = ./home/.local/usr/lib/blightmud;
|
||||||
|
recursive = true;
|
||||||
|
executable = true;
|
||||||
|
};
|
||||||
|
home.file.".config/nvim" = {
|
||||||
|
source = ./home/config/nvim;
|
||||||
|
recursive = true;
|
||||||
|
executable = true;
|
||||||
|
};
|
||||||
|
home.file.".config/dosbox-x" = {
|
||||||
|
source = ./home/config/dosbox-x;
|
||||||
|
recursive = true;
|
||||||
|
executable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
home.packages = with pkgs; [
|
||||||
|
fastfetch
|
||||||
|
ranger
|
||||||
|
zip
|
||||||
|
unzip
|
||||||
|
xz
|
||||||
|
p7zip
|
||||||
|
ripgrep
|
||||||
|
jq
|
||||||
|
eza
|
||||||
|
fzf
|
||||||
|
tmux
|
||||||
|
cowsay
|
||||||
|
lolcat
|
||||||
|
gnused
|
||||||
|
gnutar
|
||||||
|
gnupg
|
||||||
|
hugo
|
||||||
|
bat
|
||||||
|
which
|
||||||
|
nix-output-monitor
|
||||||
|
devenv
|
||||||
|
luarocks
|
||||||
|
lua5_1
|
||||||
|
gimp
|
||||||
|
lua-language-server
|
||||||
|
go
|
||||||
|
nodejs
|
||||||
|
uv
|
||||||
|
readline
|
||||||
|
cachix
|
||||||
|
sqlite
|
||||||
|
rofi
|
||||||
|
qutebrowser
|
||||||
|
foot
|
||||||
|
vifm-full
|
||||||
|
ranger
|
||||||
|
zoxide
|
||||||
|
(python313.withPackages (python-pkgs: [
|
||||||
|
python-pkgs.prompt_toolkit
|
||||||
|
python-pkgs.pygments
|
||||||
|
python-pkgs.pynvim
|
||||||
|
])
|
||||||
|
)
|
||||||
|
# vimPlugins.nvim-treesitter.withAllGrammars
|
||||||
|
neovim
|
||||||
|
zig
|
||||||
|
nodejs
|
||||||
|
go
|
||||||
|
syncthing
|
||||||
|
dosbox-x
|
||||||
|
lazygit
|
||||||
|
];
|
||||||
|
programs.neovim.plugins = [
|
||||||
|
pkgs.vimPlugins.nvim-treesitter.withAllGrammars
|
||||||
|
];
|
||||||
|
programs.taskwarrior = {
|
||||||
|
enable = true;
|
||||||
|
};
|
||||||
|
services.syncthing = {
|
||||||
|
enable = true;
|
||||||
|
};
|
||||||
|
programs.ranger = {
|
||||||
|
enable = true;
|
||||||
|
extraConfig = ''
|
||||||
|
|
||||||
|
'';
|
||||||
|
extraPackages = [ ];
|
||||||
|
mappings = {
|
||||||
|
Q = "quitall";
|
||||||
|
q = "quit";
|
||||||
|
};
|
||||||
|
plugins = [
|
||||||
|
{
|
||||||
|
name = "zoxide";
|
||||||
|
src = builtins.fetchGit {
|
||||||
|
url = "https://github.com/jchook/ranger-zoxide.git";
|
||||||
|
rev = "363df97af34c96ea873c5b13b035413f56b12ead";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "tmux";
|
||||||
|
src = builtins.fetchGit {
|
||||||
|
url = "https://github.com/joouha/ranger_tmux.git";
|
||||||
|
rev = "05ba5ddf2ce5659a90aa0ada70eb1078470d972a";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
settings = {
|
||||||
|
column_ratios = "1,3,3";
|
||||||
|
confirm_on_delete = "never";
|
||||||
|
scroll_offset = 8;
|
||||||
|
unicode_ellipsis = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
programs.fzf = {
|
||||||
|
enable = true;
|
||||||
|
tmux.enableShellIntegration = true;
|
||||||
|
enableZshIntegration = true;
|
||||||
|
colors = {
|
||||||
|
fg = "#d0d0d0";
|
||||||
|
bg = "#24283b";
|
||||||
|
hl = "#5f87af";
|
||||||
|
"fg+" = "#d0d0d0";
|
||||||
|
"bg+" = "#414868";
|
||||||
|
"hl+" = "#5fd7ff";
|
||||||
|
info = "#afaf87";
|
||||||
|
prompt = "#d7005f";
|
||||||
|
pointer = "#af5fff";
|
||||||
|
marker = "#87ff00";
|
||||||
|
spinner = "#af5fff";
|
||||||
|
header = "#87afaf";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
programs.tmux = {
|
||||||
|
enable = true;
|
||||||
|
baseIndex = 1;
|
||||||
|
clock24 = true;
|
||||||
|
disableConfirmationPrompt = true;
|
||||||
|
keyMode = "vi";
|
||||||
|
mouse = true;
|
||||||
|
newSession = true;
|
||||||
|
plugins = with pkgs; [
|
||||||
|
tmuxPlugins.cpu
|
||||||
|
{
|
||||||
|
plugin = tmuxPlugins.resurrect;
|
||||||
|
extraConfig = "set -g @resurrect-strategy-nvim 'session'";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
plugin = tmuxPlugins.continuum;
|
||||||
|
extraConfig = ''
|
||||||
|
set -g @continuum-restore 'on'
|
||||||
|
set -g @continuum-save-interval '60'
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
tmuxPlugins.yank
|
||||||
|
tmuxPlugins.vim-tmux-navigator
|
||||||
|
tmuxPlugins.vim-tmux-focus-events
|
||||||
|
tmuxPlugins.urlview
|
||||||
|
{
|
||||||
|
plugin = tmuxPlugins.tokyo-night-tmux;
|
||||||
|
extraConfig = ''
|
||||||
|
set -g @tokyo-night-tmux_window_id_style digital
|
||||||
|
set -g @tokyo-night-tmux_pane_id_style hsquare
|
||||||
|
set -g @tokyo-night-tmux_zoom_id_style dsquare
|
||||||
|
set -g @tokyo-night-tmux_show_netspeed 1
|
||||||
|
set -g @tokyo-night-tmux_netspeed_iface "wlp2s0" # Detected via default route
|
||||||
|
set -g @tokyo-night-tmux_netspeed_showip 1 # Display IPv4 address (default 0)
|
||||||
|
set -g @tokyo-night-tmux_netspeed_refresh 1 # Update interval in seconds (default 1)
|
||||||
|
set -g @tokyo-night-tmux_show_path 1
|
||||||
|
set -g @tokyo-night-tmux_path_format relative # 'relative' or 'full'
|
||||||
|
set -g @tokyo-night-tmux_show_battery_widget 1
|
||||||
|
set -g @tokyo-night-tmux_battery_name "BAT0" # some linux distro have 'BAT0'
|
||||||
|
set -g @tokyo-night-tmux_battery_low_threshold 21 # default
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
tmuxPlugins.tmux-fzf
|
||||||
|
# {
|
||||||
|
# plugin = tmuxPlugins.tilish;
|
||||||
|
# extraConfig = ''
|
||||||
|
# set -g @tilish-navigator 'on'
|
||||||
|
# set -g @tilish-default 'main-vertical'
|
||||||
|
# set -g @tilish-enforce 'none'
|
||||||
|
# set -g escape-time 0
|
||||||
|
# set -g @tilish-dmenu 'on'
|
||||||
|
# '';
|
||||||
|
# }
|
||||||
|
|
||||||
|
];
|
||||||
|
prefix = "C-a";
|
||||||
|
shell = "${pkgs.zsh}/bin/zsh";
|
||||||
|
# terminal = "xterm-kitty:RGB";
|
||||||
|
tmuxinator.enable = true;
|
||||||
|
extraConfig = ''
|
||||||
|
set-option -g status-position top
|
||||||
|
set -g default-terminal 'tmux-256color'
|
||||||
|
set -g terminal-overrides ',xterm-256color:RGB'
|
||||||
|
bind-key b choose-tree -Z "run-shell 'tmux swap-pane -s %%'"
|
||||||
|
# bind C-p display-popup -E -w 60% -h 70% 'tmuxsessions.sh'
|
||||||
|
bind C-p run-shell 'tmuxsessions.sh'
|
||||||
|
bind C-d run-shell 'dotfile-picker.sh'
|
||||||
|
bind [ run-shell 'project-picker.sh'
|
||||||
|
# bind C-c display-popup -E -w 50% -h 50% 'nvim +":cd ~/org" ~/org/refile.norg'
|
||||||
|
# bind C-c display-popup -E -w 50% -h 50% 'nvim +"VimwikiIndex"
|
||||||
|
bind C-c display-popup -E -w 40% -h 60% "pytui -n"
|
||||||
|
bind C-w display-popup -E -w 40% -h 60% "pytui -D"
|
||||||
|
|
||||||
|
bind C-o display-popup -E -w 50% -h 50% 'igrep ~/wiki/notes'
|
||||||
|
|
||||||
|
bind j run-shell 'popuptmux'
|
||||||
|
bind r source-file ~/.tmux.conf \; display "Reloaded!"
|
||||||
|
bind i split-window -v -c '\
|
||||||
|
#{pane_current_path}' 'emojicherrypick.py --menu fzf\
|
||||||
|
'
|
||||||
|
bind-key -n F4 run-shell 'ranger'
|
||||||
|
# bind-key -n C-e split-window -v -c '\
|
||||||
|
# #{pane_current_path}' 'vifm\
|
||||||
|
# '
|
||||||
|
bind-key -n C-f split-window 'ranger .'
|
||||||
|
bind F3 send-keys 'igrep .' C-m
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
programs.git = {
|
||||||
|
enable = true;
|
||||||
|
userName = "th3r00t";
|
||||||
|
userEmail = "tty303@proton.me";
|
||||||
|
};
|
||||||
|
programs.direnv = {
|
||||||
|
enable = true;
|
||||||
|
enableZshIntegration = true;
|
||||||
|
nix-direnv.enable = true;
|
||||||
|
};
|
||||||
|
programs.eza = {
|
||||||
|
enable = true;
|
||||||
|
enableBashIntegration = true;
|
||||||
|
enableZshIntegration = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# starship - an customizable prompt for any shell
|
||||||
|
programs.starship = {
|
||||||
|
enable = true;
|
||||||
|
# custom settings
|
||||||
|
settings = {
|
||||||
|
add_newline = false;
|
||||||
|
aws.disabled = true;
|
||||||
|
gcloud.disabled = true;
|
||||||
|
line_break.disabled = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
programs.zsh = {
|
||||||
|
enable = true;
|
||||||
|
sessionVariables = {
|
||||||
|
PATH="$PATH:$HOME/.local/usr/bin";
|
||||||
|
};
|
||||||
|
oh-my-zsh = {
|
||||||
|
enable = true;
|
||||||
|
plugins = [
|
||||||
|
"git"
|
||||||
|
"colored-man-pages"
|
||||||
|
"colorize"
|
||||||
|
"command-not-found"
|
||||||
|
"compleat"
|
||||||
|
"dirhistory"
|
||||||
|
"fzf"
|
||||||
|
"git-auto-fetch"
|
||||||
|
"git-extras"
|
||||||
|
"git-prompt"
|
||||||
|
"gitignore"
|
||||||
|
"gpg-agent"
|
||||||
|
"history"
|
||||||
|
"jsontools"
|
||||||
|
"man"
|
||||||
|
"nmap"
|
||||||
|
"pip"
|
||||||
|
"python"
|
||||||
|
"ssh-agent"
|
||||||
|
"sudo"
|
||||||
|
"tmux"
|
||||||
|
"vi-mode"
|
||||||
|
"zsh-navigation-tools"
|
||||||
|
];
|
||||||
|
# theme = "starship";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
programs.bash = {
|
||||||
|
enable = true;
|
||||||
|
enableCompletion = true;
|
||||||
|
bashrcExtra = ''
|
||||||
|
export PATH="$PATH:$HOME/.local/usr/bin";
|
||||||
|
'';
|
||||||
|
shellAliases = {
|
||||||
|
urlencode = "python3 -c 'import sys, urllib.parse as ul; print(ul.quote_plus(sys.stdin.read()))'";
|
||||||
|
urldecode = "python3 -c 'import sys, urllib.parse as ul; print(il.unquote_plus(sys.stdin.read()))'";
|
||||||
|
ls = "eza";
|
||||||
|
cat = "bat";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
home.stateVersion = "25.05";
|
||||||
|
}
|
||||||
1
home/.local/usr/bin/ShadowPCBeta.AppImage
Symbolic link
1
home/.local/usr/bin/ShadowPCBeta.AppImage
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
/home/th3r00t/Downloads/ShadowPCBeta.AppImage
|
||||||
67
home/.local/usr/bin/addpass
Executable file
67
home/.local/usr/bin/addpass
Executable file
@@ -0,0 +1,67 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
source $HOME/.config/rofi-pass/config
|
||||||
|
|
||||||
|
if [[ -n "$3" && "$2" == "--root" ]]; then
|
||||||
|
root="${2}"
|
||||||
|
elif [[ -n $root ]]; then
|
||||||
|
root=$root
|
||||||
|
elif [[ -n $PASSWORD_STORE_DIR ]]; then
|
||||||
|
root=$PASSWORD_STORE_DIR
|
||||||
|
else
|
||||||
|
root="$HOME/.password-store"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $1 == "--help" || $1 == "-h" ]]; then
|
||||||
|
echo "add pass files for rofi-pass"
|
||||||
|
echo "(C) 2015 Rasmus Steinke <rasi at xssn dot at>"
|
||||||
|
echo ""
|
||||||
|
echo "--name \"foobar\" Mandatory first argument - filename of password file"
|
||||||
|
echo "--root \"foobar\" Optional second argument - Absolute path to password store"
|
||||||
|
echo ""
|
||||||
|
echo "+FIELD \"barbaz\" Every field name has to start with \"+\""
|
||||||
|
echo " Values should be quoted"
|
||||||
|
echo ""
|
||||||
|
echo "Example:"
|
||||||
|
echo "addpass --name \"my password file\" --root \"$HOME/passwords\" +user \"Richard\" +foo \"bar\" +autotype \"foo :tab user :tab pass\""
|
||||||
|
exit
|
||||||
|
else
|
||||||
|
echo "$1"
|
||||||
|
if [[ $1 != "--name" ]]; then
|
||||||
|
echo "Missing --name option. Try --help"
|
||||||
|
exit
|
||||||
|
elif [[ $1 == "--name" ]]; then
|
||||||
|
Name="$2"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Using database \"$root\""
|
||||||
|
|
||||||
|
OIFS=$IFS;
|
||||||
|
IFS="+";
|
||||||
|
|
||||||
|
fields="$@";
|
||||||
|
fieldsArray=($fields);
|
||||||
|
read -p "Enter password for entry \"${Name}\" > " -s pass
|
||||||
|
|
||||||
|
cd "${root}"
|
||||||
|
group=$(echo -e "No Group\n---\n$(find -type d -not -iwholename '*.git*' -printf '%d\t%P\n' | sort -r -nk1 | cut -f2-)" | rofi -dmenu -p "Choose Group > ")
|
||||||
|
|
||||||
|
echo -e "\n\nStoring file ${Name} in group ${group}"
|
||||||
|
|
||||||
|
printEntry () {
|
||||||
|
echo -e "$pass\n---"
|
||||||
|
for ((i=1; i<${#fieldsArray[@]}; ++i)); do
|
||||||
|
field=$(echo "${fieldsArray[$i]}" | awk -F' ' '{print $1}')
|
||||||
|
option=$(echo "${fieldsArray[$i]}" | cut -d ' ' -f 2- | sed -e 's/[[:blank:]]\+$//')
|
||||||
|
echo "$field: $option" | grep -Ev 'name:|--root|root:|^:' #${fieldsArray[$i]}";
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "$group" == "No Group" ]]; then
|
||||||
|
printEntry | PASSWORD_STORE_DIR="${root}" pass insert -m "${Name}"
|
||||||
|
elif [[ "$group" == "" ]]; then
|
||||||
|
exit
|
||||||
|
else
|
||||||
|
printEntry | PASSWORD_STORE_DIR="${root}" pass insert -m "${group}/${Name}"
|
||||||
|
fi
|
||||||
7
home/.local/usr/bin/baraction.sh
Executable file
7
home/.local/usr/bin/baraction.sh
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
SLEEP_SEC=5
|
||||||
|
COUNT=0
|
||||||
|
while :; do
|
||||||
|
let COUNT=$COUNT+1
|
||||||
|
echo -e " HELLO $COUNT"
|
||||||
|
sleep $SLEEP_SEC
|
||||||
|
done
|
||||||
1
home/.local/usr/bin/blightmud
Symbolic link
1
home/.local/usr/bin/blightmud
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
/home/th3r00t/.local/build/Blightmud/target/release/blightmud
|
||||||
2
home/.local/usr/bin/butlerianjihad.sh
Executable file
2
home/.local/usr/bin/butlerianjihad.sh
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
mpv /mnt/audiobooks/Dune\ -\ Audiobook\ Collection\ 2015/03\ -\ Legends\ of\ Dune/01.\ The\ Butlerian\ Jihad.m4b
|
||||||
56
home/.local/usr/bin/capture-note.sh
Executable file
56
home/.local/usr/bin/capture-note.sh
Executable file
@@ -0,0 +1,56 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Set directory path for Vimwiki files
|
||||||
|
WIKI_DIR="$HOME/org/wiki" # Replace with the path to your Vimwiki directory
|
||||||
|
# Get the list of existing note titles, replacing underscores with spaces for display
|
||||||
|
EXISTING_TITLES=$(find "$WIKI_DIR/notes" -type f -name "*.wiki" -exec basename {} .wiki \; | tr '_' ' ')
|
||||||
|
# Use fzf to let the user select an existing title or type a new one
|
||||||
|
TITLE=$( (echo "$EXISTING_TITLES" && echo "[New Note]") | fzf --prompt="Select or enter title: " --print-query)
|
||||||
|
|
||||||
|
# Check if the user chose an existing title or opted for a new note
|
||||||
|
if [[ "$TITLE" = "[New Note]" || -z "$TITLE" ]]; then
|
||||||
|
# Prompt for a new title if "New Note" was selected
|
||||||
|
TITLE=$(echo "" | fzf --prompt="Enter title for new entry: ")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Exit if no title was entered
|
||||||
|
if [[ -z "$TITLE" ]]; then
|
||||||
|
echo "No title entered. Exiting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Format the filename by replacing spaces with underscores and lowercasing
|
||||||
|
FILENAME_TIMESTAMP=$(date +"%Y%m%d%H%M")
|
||||||
|
FILENAME="${FILENAME_TIMESTAMP}-$(echo "$TITLE" | tr ' ' '_' | tr '[:upper:]' '[:lower:]').wiki"
|
||||||
|
NEW_FILE="$WIKI_DIR/notes/$FILENAME"
|
||||||
|
|
||||||
|
# Check if a file with this title already exists
|
||||||
|
EXISTING_FILE=$(find "$WIKI_DIR/notes" -type f -name "$(echo "$TITLE" | tr ' ' '_' | tr '[:upper:]' '[:lower:]').wiki")
|
||||||
|
|
||||||
|
if [[ -n "$EXISTING_FILE" ]]; then
|
||||||
|
# Open the existing file in Neovim if found
|
||||||
|
nvim "$EXISTING_FILE"
|
||||||
|
else
|
||||||
|
# Create a new file with the specified template if it does not exist
|
||||||
|
TIMESTAMP=$(date +"%Y-%m-%d %H:%M")
|
||||||
|
|
||||||
|
echo "= $TITLE =
|
||||||
|
*Created:* $TIMESTAMP
|
||||||
|
|
||||||
|
== Summary ==
|
||||||
|
|
||||||
|
== Tasks ==
|
||||||
|
|
||||||
|
== Notes ==
|
||||||
|
|
||||||
|
== Resources ==
|
||||||
|
* [[wiki link]] for additional content
|
||||||
|
* [[other wiki link|Desc]]
|
||||||
|
" > "$NEW_FILE"
|
||||||
|
|
||||||
|
# Add a link to the new file at the bottom of index.wiki
|
||||||
|
echo "- [[$FILENAME|$TITLE]]" >> "$WIKI_DIR/index.wiki"
|
||||||
|
|
||||||
|
# Open the new file in Neovim
|
||||||
|
nvim "$NEW_FILE"
|
||||||
|
fi
|
||||||
14
home/.local/usr/bin/chatgpt.js
Executable file
14
home/.local/usr/bin/chatgpt.js
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import { ChatGPTAPIBrowser } from 'chatgpt'
|
||||||
|
|
||||||
|
async function example() {
|
||||||
|
const api = new ChatGPTAPIBrowser({
|
||||||
|
email: process.env.OPENAI_EMAIL,
|
||||||
|
password: process.env.OPENAI_PASSWORD
|
||||||
|
})
|
||||||
|
|
||||||
|
await api.initSession()
|
||||||
|
const result = await api.sendMessage("Hello World")
|
||||||
|
console.log(result.rseponse)
|
||||||
|
}
|
||||||
24
home/.local/usr/bin/dotfile-picker.sh
Executable file
24
home/.local/usr/bin/dotfile-picker.sh
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Set the directory where your dotfiles are located
|
||||||
|
DOTFILES_DIR="${HOME}/.dotfiles"
|
||||||
|
|
||||||
|
# Use fzf to select a file
|
||||||
|
file=$(find "$DOTFILES_DIR" -type f -name "*.*" | \
|
||||||
|
fzf --delimiter / --with-nth=-1 --keep-right \
|
||||||
|
--prompt="Dotfiles " \
|
||||||
|
--tmux left,40 --reverse \
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check if a directory was selected
|
||||||
|
if [[ -n "$file" ]]; then
|
||||||
|
projectname="${file##*/}"
|
||||||
|
escprojectname = $(printf '%q' "$projectname")
|
||||||
|
# Check if a tmux window with the project name already exists
|
||||||
|
if tmux list-windows -F "#{window_name}" | grep -q "^$escprojectname$"; then
|
||||||
|
tmux select-window -t "$projectname"
|
||||||
|
else
|
||||||
|
# Create a new tmux window with the project name and open nvim in the folder
|
||||||
|
tmux new-window -n "$projectname" "nvim '$file'"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
2
home/.local/usr/bin/dropdown
Executable file
2
home/.local/usr/bin/dropdown
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
urxvt -name dropdown -e tmux attach Dropdown &
|
||||||
898
home/.local/usr/bin/emojicherrypick.py
Executable file
898
home/.local/usr/bin/emojicherrypick.py
Executable file
@@ -0,0 +1,898 @@
|
|||||||
|
#!/bin/env python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import urllib.request
|
||||||
|
import subprocess
|
||||||
|
import random
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Tuple
|
||||||
|
from typing import TypeAlias
|
||||||
|
|
||||||
|
CompletedProcess: TypeAlias = subprocess.CompletedProcess
|
||||||
|
|
||||||
|
|
||||||
|
class App:
|
||||||
|
""" Contains all settings and meta information for the application. """
|
||||||
|
|
||||||
|
name: str = 'emojicherrypick'
|
||||||
|
version: str = '0.2'
|
||||||
|
|
||||||
|
def __init__(self, args: argparse.Namespace) -> None:
|
||||||
|
""" Construct application attributes used as settings. """
|
||||||
|
|
||||||
|
self.list_version: bool = args.version
|
||||||
|
self.frozen: bool = bool(getattr(sys, 'frozen', False)
|
||||||
|
and hasattr(sys, '_MEIPASS'))
|
||||||
|
self.wipe_cache: bool = args.wipe_cache
|
||||||
|
self.offline: bool = args.offline
|
||||||
|
self.menu: str = args.menu
|
||||||
|
self.url: str = args.url
|
||||||
|
self.cache_dir: Path = fullpath(args.cache_dir)
|
||||||
|
self.db_source: Path = Path(self.cache_dir / 'emojis.json')
|
||||||
|
self.noemojis: bool = args.noemojis
|
||||||
|
self.db_filtered: Path | None = None
|
||||||
|
if not self.noemojis:
|
||||||
|
self.db_filtered = self.db_source.with_suffix('.cherry')
|
||||||
|
self.nofavorites: bool = args.nofavorites
|
||||||
|
self.db_favorites: Path | None = None
|
||||||
|
if not self.nofavorites:
|
||||||
|
self.db_favorites = fullpath(args.favorites)
|
||||||
|
self.recents_size: int = args.recents_size
|
||||||
|
self.norecents: bool = args.norecents
|
||||||
|
self.db_recents: Path | None = None
|
||||||
|
if not self.norecents:
|
||||||
|
self.db_recents = fullpath(args.recents)
|
||||||
|
self.font_family: str = args.font_family
|
||||||
|
self.font_size: int = args.font_size
|
||||||
|
self.list_size: int = args.list_size
|
||||||
|
self.selected_emoji: str | None = None
|
||||||
|
self.selected_desc: str | None = None
|
||||||
|
self.stdout: bool = args.stdout and not args.nostdout
|
||||||
|
self.clipboard: bool = args.clipboard and not args.noclipboard
|
||||||
|
self.notify: bool = args.notify and not args.nonotify
|
||||||
|
self.typing: bool = args.typing and not args.notyping
|
||||||
|
self.ignore_case: bool = args.ignore_case and not args.noignore_case
|
||||||
|
self.ignore_skin: bool = args.ignore_skin
|
||||||
|
self.matching_rofi: str = args.matching_rofi
|
||||||
|
self.pattern: str = args.pattern
|
||||||
|
self.prompt: str = args.prompt
|
||||||
|
self.list_programs: bool = args.list_programs
|
||||||
|
self.programs: dict[str, Path] = {
|
||||||
|
'Python': Path(sys.executable),
|
||||||
|
'rofi': App.which(args.rofi),
|
||||||
|
'dmenu': App.which(args.dmenu),
|
||||||
|
'pmenu': App.which(args.pmenu),
|
||||||
|
'fzf': App.which(args.fzf),
|
||||||
|
'xclip': App.which(args.xclip),
|
||||||
|
'xdotool': App.which(args.xdotool),
|
||||||
|
'notify-send': App.which(args.notifysend),
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.wipe_cache:
|
||||||
|
self.wipe_cache_files()
|
||||||
|
if not self.offline or not self.noemojis:
|
||||||
|
self.download_db_source()
|
||||||
|
self.filter_db_source()
|
||||||
|
|
||||||
|
def load_emoji_list(self, aslist=False) -> str | list:
|
||||||
|
""" Read all emojis, recents and favorites into a single string. """
|
||||||
|
|
||||||
|
emoji_list: str = ''
|
||||||
|
filtered_list: str = ''
|
||||||
|
recents_list: str = ''
|
||||||
|
favorites_list: str = ''
|
||||||
|
if (not self.norecents
|
||||||
|
and self.db_recents
|
||||||
|
and self.db_recents.exists()):
|
||||||
|
recents_list = self.db_recents.read_text().strip('\n')
|
||||||
|
recents_top: list = recents_list.splitlines()
|
||||||
|
recents_top.reverse()
|
||||||
|
recents_top = list(dict.fromkeys(recents_top))
|
||||||
|
recents_top = recents_top[0:self.recents_size]
|
||||||
|
recents_list = '\n'.join(recents_top)
|
||||||
|
if (not self.nofavorites
|
||||||
|
and self.db_favorites
|
||||||
|
and self.db_favorites.exists()):
|
||||||
|
favorites_list = self.db_favorites.read_text().strip('\n')
|
||||||
|
if (not self.noemojis
|
||||||
|
and self.db_filtered
|
||||||
|
and self.db_filtered.exists()):
|
||||||
|
filtered_list = self.db_filtered.read_text().strip('\n')
|
||||||
|
if recents_list:
|
||||||
|
emoji_list += '\n' + recents_list
|
||||||
|
if favorites_list:
|
||||||
|
emoji_list += '\n' + favorites_list
|
||||||
|
if filtered_list:
|
||||||
|
emoji_list += '\n' + filtered_list
|
||||||
|
elist: list[str] = list(dict.fromkeys(emoji_list.splitlines()))
|
||||||
|
if aslist:
|
||||||
|
return elist
|
||||||
|
else:
|
||||||
|
emoji_list = '\n'.join(elist)
|
||||||
|
return emoji_list.lstrip('\n')
|
||||||
|
|
||||||
|
def wipe_cache_files(self) -> None:
|
||||||
|
""" Clean cache by deleting all known files in it. """
|
||||||
|
|
||||||
|
if self.db_source:
|
||||||
|
self.db_source.unlink(missing_ok=True)
|
||||||
|
if self.db_filtered:
|
||||||
|
self.db_filtered.unlink(missing_ok=True)
|
||||||
|
if self.db_recents:
|
||||||
|
self.db_recents.unlink(missing_ok=True)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def download_db_source(self, force=False):
|
||||||
|
""" Download emojis.json database source from URL to cache. """
|
||||||
|
|
||||||
|
if force:
|
||||||
|
self.db_source.unlink(missing_ok=True)
|
||||||
|
if not self.db_source.exists():
|
||||||
|
self.cache_dir.mkdir(exist_ok=True)
|
||||||
|
self.db_filtered.unlink(missing_ok=True)
|
||||||
|
response = urllib.request.urlopen(self.url)
|
||||||
|
data = response.read()
|
||||||
|
text = data.decode('utf-8')
|
||||||
|
self.db_source.write_text(text)
|
||||||
|
|
||||||
|
def filter_db_source(self, force=False):
|
||||||
|
""" Convert, filter and sort cached database to a small text file. """
|
||||||
|
|
||||||
|
def sorted_by_order(elem):
|
||||||
|
""" Used to determined sort key by 'order' for sorted(). """
|
||||||
|
|
||||||
|
return elem['order']
|
||||||
|
|
||||||
|
if force:
|
||||||
|
self.db_filtered.unlink(missing_ok=True)
|
||||||
|
if self.db_filtered and not self.db_filtered.exists():
|
||||||
|
source = json.loads(self.db_source.read_text())
|
||||||
|
filtered: str = ''
|
||||||
|
emojis_face: str = ''
|
||||||
|
emojis_finger: str = ''
|
||||||
|
emojis_other: str = ''
|
||||||
|
for emoji in sorted(source['emojis'], key=sorted_by_order):
|
||||||
|
|
||||||
|
# Exclude emojis that have "skin" in their names, as they are
|
||||||
|
# mostly color variations of the main emoji.
|
||||||
|
not_ignored_by_skin = 'skin' not in emoji['name'] \
|
||||||
|
and 'skin_tone' not in emoji['shortname'] if self.ignore_skin \
|
||||||
|
else True
|
||||||
|
if (not_ignored_by_skin and emoji['name']):
|
||||||
|
|
||||||
|
# Format:
|
||||||
|
# ☺️ smiling face Smileys & Emotion (face-affection)
|
||||||
|
str_emoji: str = (emoji['emoji'].strip()
|
||||||
|
+ ' '
|
||||||
|
+ emoji['name'].strip()
|
||||||
|
+ ' ~ '
|
||||||
|
+ emoji['category'].strip())
|
||||||
|
|
||||||
|
# Create multiple lists with emojis, so later it can be put
|
||||||
|
# together for sorted groups.
|
||||||
|
if ('face' in emoji['name']
|
||||||
|
or 'face' in emoji['category']):
|
||||||
|
emojis_face += str_emoji + '\n'
|
||||||
|
elif 'finger' in emoji['category']:
|
||||||
|
emojis_finger += str_emoji + '\n'
|
||||||
|
else:
|
||||||
|
emojis_other += str_emoji + '\n'
|
||||||
|
|
||||||
|
filtered = emojis_face + emojis_finger + emojis_other
|
||||||
|
self.db_filtered.write_text(filtered.strip('\n'))
|
||||||
|
|
||||||
|
def update_selected_emoji(self, emoji: list | None) -> str | None:
|
||||||
|
""" Update last selected emoji and return by stripping newlines. """
|
||||||
|
|
||||||
|
if emoji is None:
|
||||||
|
self.selected_emoji = None
|
||||||
|
self.selected_desc = None
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
emoji = [emoji[0].strip('\n'), emoji[1].strip('\n')]
|
||||||
|
self.selected_emoji = emoji[0]
|
||||||
|
self.selected_desc = emoji[1]
|
||||||
|
self.append_recents()
|
||||||
|
except (ValueError, AttributeError, IndexError):
|
||||||
|
self.selected_emoji = None
|
||||||
|
self.selected_desc = None
|
||||||
|
return self.selected_emoji
|
||||||
|
|
||||||
|
def select_by_none(self):
|
||||||
|
""" Selects nothing and resets last selected emoji. """
|
||||||
|
|
||||||
|
return self.update_selected_emoji(None)
|
||||||
|
|
||||||
|
def select_by_random(self):
|
||||||
|
""" Selects an emoji by random chance. """
|
||||||
|
|
||||||
|
random_set: set = set(self.load_emoji_list(aslist=True))
|
||||||
|
random_set.discard('')
|
||||||
|
random_list: list = list(random_set)
|
||||||
|
random.shuffle(random_list)
|
||||||
|
emoji = random_list[0].split(' ', 1)
|
||||||
|
return self.update_selected_emoji(emoji)
|
||||||
|
|
||||||
|
def select_by_filter(self) -> str | None:
|
||||||
|
""" Select an emoji without a menu but first match on a filter. """
|
||||||
|
|
||||||
|
emoji_list: str | list = self.load_emoji_list(aslist=True)
|
||||||
|
if self.ignore_case:
|
||||||
|
emoji_list = list(filter(
|
||||||
|
lambda line: self.pattern.lower() in line.lower(),
|
||||||
|
emoji_list
|
||||||
|
))
|
||||||
|
else:
|
||||||
|
emoji_list = list(filter(
|
||||||
|
lambda line: self.pattern in line,
|
||||||
|
emoji_list
|
||||||
|
))
|
||||||
|
try:
|
||||||
|
emoji = emoji_list[0].split(' ', 1)
|
||||||
|
except (ValueError, AttributeError, IndexError):
|
||||||
|
emoji = None
|
||||||
|
return self.update_selected_emoji(emoji)
|
||||||
|
|
||||||
|
def select_by_dmenu(self):
|
||||||
|
""" Select an emoji with dmenu and get emoji and desc tuple. """
|
||||||
|
|
||||||
|
command: list[str] = []
|
||||||
|
command.append(self.programs['dmenu'].as_posix())
|
||||||
|
command.append('-p')
|
||||||
|
command.append(self.prompt)
|
||||||
|
command.append('-l')
|
||||||
|
command.append(str(self.list_size))
|
||||||
|
command.append('-fn')
|
||||||
|
command.append(f'"{self.font_family}-{str(self.font_size)}"')
|
||||||
|
emoji_list = self.load_emoji_list()
|
||||||
|
if self.ignore_case:
|
||||||
|
emoji_list = emoji_list.lower()
|
||||||
|
emoji = App.select_command_emoji(command, emoji_list)
|
||||||
|
return self.update_selected_emoji(emoji)
|
||||||
|
|
||||||
|
def select_by_rofi(self):
|
||||||
|
""" Select an emoji with rofi and get emoji and desc tuple. """
|
||||||
|
|
||||||
|
command: list[str] = []
|
||||||
|
command.append(self.programs['rofi'].as_posix())
|
||||||
|
command.append('-dmenu')
|
||||||
|
command.append('-steal-focus')
|
||||||
|
command.append('-p')
|
||||||
|
command.append(self.prompt)
|
||||||
|
command.append('-title')
|
||||||
|
command.append(self.name)
|
||||||
|
command.append('-l')
|
||||||
|
command.append(str(self.list_size))
|
||||||
|
command.append('-font')
|
||||||
|
command.append(f'"{self.font_family} {str(self.font_size)}"')
|
||||||
|
command.append('-no-custom')
|
||||||
|
command.append('-matching')
|
||||||
|
command.append(self.matching_rofi)
|
||||||
|
if self.ignore_case:
|
||||||
|
command.append('-i')
|
||||||
|
command.append('-nocase-sensitive')
|
||||||
|
emoji_list = self.load_emoji_list()
|
||||||
|
emoji = App.select_command_emoji(command, emoji_list)
|
||||||
|
return self.update_selected_emoji(emoji)
|
||||||
|
|
||||||
|
def select_by_pmenu(self):
|
||||||
|
""" Select an emoji with pmenu and get emoji and desc tuple. """
|
||||||
|
|
||||||
|
command: list[str] = []
|
||||||
|
command.append(self.programs['pmenu'].as_posix())
|
||||||
|
command.append('-p')
|
||||||
|
command.append(self.prompt)
|
||||||
|
emoji_list = self.load_emoji_list()
|
||||||
|
if self.ignore_case:
|
||||||
|
emoji_list = emoji_list.lower()
|
||||||
|
emoji = App.select_command_emoji(command, emoji_list)
|
||||||
|
return self.update_selected_emoji(emoji)
|
||||||
|
|
||||||
|
def select_by_fzf(self):
|
||||||
|
""" Select an emoji with fzf and get emoji and desc tuple. """
|
||||||
|
|
||||||
|
command: list[str] = []
|
||||||
|
command.append(self.programs['fzf'].as_posix())
|
||||||
|
command.append('--layout')
|
||||||
|
command.append('reverse')
|
||||||
|
command.append('--prompt')
|
||||||
|
command.append(self.prompt)
|
||||||
|
if self.pattern:
|
||||||
|
command.append('--filter')
|
||||||
|
command.append(self.pattern)
|
||||||
|
if self.ignore_case:
|
||||||
|
command.append('-i')
|
||||||
|
emoji_list = self.load_emoji_list()
|
||||||
|
emoji = App.select_command_emoji(command, emoji_list)
|
||||||
|
return self.update_selected_emoji(emoji)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def select_command_emoji(
|
||||||
|
cls,
|
||||||
|
command,
|
||||||
|
emoji_list) -> Tuple[str, str] | Tuple[None, None]:
|
||||||
|
""" Return selected emoji and desc from list using custom command. """
|
||||||
|
|
||||||
|
output_p: CompletedProcess | None = None
|
||||||
|
try:
|
||||||
|
output_p = subprocess.run(command,
|
||||||
|
input=emoji_list,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
text=True)
|
||||||
|
except FileNotFoundError:
|
||||||
|
raise subprocess.SubprocessError
|
||||||
|
if output_p and output_p.stdout:
|
||||||
|
try:
|
||||||
|
emoji, desc = output_p.stdout.split(' ', 1)
|
||||||
|
return emoji.strip(' \n'), desc.strip(' \n')
|
||||||
|
except ValueError:
|
||||||
|
return None, None
|
||||||
|
else:
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
def send_emoji_to_stdout(self, newline=True) -> None:
|
||||||
|
""" Print out emoji to stdout. """
|
||||||
|
|
||||||
|
if newline:
|
||||||
|
print(self.selected_emoji)
|
||||||
|
else:
|
||||||
|
print(self.selected_emoji, end='')
|
||||||
|
|
||||||
|
def send_emoji_to_clipboard(self) -> subprocess.Popen | None:
|
||||||
|
""" Copy emoji to systems clipboard. """
|
||||||
|
|
||||||
|
command: list[str] = []
|
||||||
|
command.append(self.programs['xclip'].as_posix())
|
||||||
|
command.append('-rmlastnl')
|
||||||
|
command.append('-selection')
|
||||||
|
command.append('clipboard')
|
||||||
|
xclip_p: subprocess.Popen | None = None
|
||||||
|
xclip_p = subprocess.Popen(command,
|
||||||
|
stdin=subprocess.PIPE,
|
||||||
|
text=True)
|
||||||
|
if xclip_p:
|
||||||
|
try:
|
||||||
|
xclip_p.communicate(input=(self.selected_emoji), timeout=2)
|
||||||
|
if xclip_p.returncode:
|
||||||
|
raise subprocess.SubprocessError
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
xclip_p.kill()
|
||||||
|
xclip_p = None
|
||||||
|
raise subprocess.SubprocessError
|
||||||
|
else:
|
||||||
|
xclip_p = None
|
||||||
|
raise subprocess.SubprocessError
|
||||||
|
return xclip_p
|
||||||
|
|
||||||
|
def send_emoji_to_typing(self) -> CompletedProcess | None:
|
||||||
|
""" Output emoji to active window as if user typed it on keyboard. """
|
||||||
|
|
||||||
|
command: list[str] = []
|
||||||
|
command.append(self.programs['xdotool'].as_posix())
|
||||||
|
command.append('getwindowfocus')
|
||||||
|
command.append('windowfocus')
|
||||||
|
command.append('--sync')
|
||||||
|
command.append('type')
|
||||||
|
command.append('--clearmodifiers')
|
||||||
|
command.append('--delay')
|
||||||
|
command.append('25')
|
||||||
|
if self.selected_emoji:
|
||||||
|
command.append(self.selected_emoji)
|
||||||
|
xdotool_p: CompletedProcess | None = None
|
||||||
|
xdotool_p = subprocess.run(command,
|
||||||
|
stdin=subprocess.PIPE,
|
||||||
|
text=True,
|
||||||
|
check=True,
|
||||||
|
timeout=1)
|
||||||
|
return xdotool_p
|
||||||
|
|
||||||
|
def send_emoji_to_notify(self) -> CompletedProcess | None:
|
||||||
|
""" Send the emoji as a notification message. """
|
||||||
|
|
||||||
|
command: list[str] = []
|
||||||
|
command.append(self.programs['notify-send'].as_posix())
|
||||||
|
command.append('--urgency=low')
|
||||||
|
if self.selected_emoji:
|
||||||
|
command.append(self.selected_emoji)
|
||||||
|
notify_p: CompletedProcess | None = None
|
||||||
|
notify_p = subprocess.run(command,
|
||||||
|
stdin=subprocess.PIPE,
|
||||||
|
text=True,
|
||||||
|
check=True,
|
||||||
|
timeout=1)
|
||||||
|
return notify_p
|
||||||
|
|
||||||
|
def append_recents(self) -> bool:
|
||||||
|
""" Append the last selected emoji entry to the recents file. """
|
||||||
|
|
||||||
|
if (not self.norecents
|
||||||
|
and self.db_recents
|
||||||
|
and self.selected_emoji
|
||||||
|
and self.selected_desc):
|
||||||
|
line: str = ''
|
||||||
|
if self.db_recents.exists():
|
||||||
|
line = '\n'
|
||||||
|
self.trim_recents_file()
|
||||||
|
line += self.selected_emoji + ' ' + self.selected_desc
|
||||||
|
with open(self.db_recents, 'a') as file:
|
||||||
|
file.write(line)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def trim_recents_file(self) -> bool:
|
||||||
|
""" Shortens and strips recents file if it gets big. """
|
||||||
|
|
||||||
|
max_byte_size: int = 4096
|
||||||
|
max_list_entries: int = 50
|
||||||
|
if (self.db_recents
|
||||||
|
and self.db_recents.stat().st_size > max_byte_size):
|
||||||
|
data: str = self.db_recents.read_text().strip('\n')
|
||||||
|
recents_list: list = data.splitlines()
|
||||||
|
recents_list.reverse()
|
||||||
|
recents_list = list(dict.fromkeys(recents_list))
|
||||||
|
recents_list = recents_list[0:max_list_entries]
|
||||||
|
recents_list.reverse()
|
||||||
|
data = '\n'.join(recents_list)
|
||||||
|
self.db_recents.unlink(missing_ok=True)
|
||||||
|
self.db_recents.write_text(data)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def print_version(self):
|
||||||
|
""" Print version and frozen state of this program. """
|
||||||
|
|
||||||
|
if self.frozen:
|
||||||
|
frozen = ' (pyinstaller)'
|
||||||
|
else:
|
||||||
|
frozen = ''
|
||||||
|
print(f'{self.name} v{self.version}{frozen}')
|
||||||
|
|
||||||
|
def print_list_programs(self):
|
||||||
|
""" Print all program names and paths to stdout. """
|
||||||
|
|
||||||
|
for name, path in self.programs.items():
|
||||||
|
print(name + ':', path.as_posix())
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def which(cls, command: str) -> Path:
|
||||||
|
""" Find command in $PATH or get fullpath. """
|
||||||
|
|
||||||
|
program: str | None = shutil.which(command)
|
||||||
|
path: Path
|
||||||
|
if program:
|
||||||
|
path = Path(program)
|
||||||
|
else:
|
||||||
|
path = fullpath(command)
|
||||||
|
if not path.is_file():
|
||||||
|
path = Path(command)
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def fullpath(file: str) -> Path:
|
||||||
|
""" Transform str to path, resolve env vars, tilde and make absolute. """
|
||||||
|
|
||||||
|
expandedfile: str = os.path.expandvars(file)
|
||||||
|
path: Path = Path(expandedfile).expanduser().resolve()
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def parse_arguments(args: list[str] | None = None) -> argparse.Namespace:
|
||||||
|
""" Programs CLI options. """
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description=('🍒⛏️ Emoji Cherry Pick - Select an emoji and go wild.'),
|
||||||
|
epilog=('Copyright © 2022 Tuncay D. '
|
||||||
|
'<https://github.com/thingsiplay/emojicherrypick>'),
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'--version',
|
||||||
|
default=False,
|
||||||
|
action='store_true',
|
||||||
|
help='print version and exit'
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'--list-programs',
|
||||||
|
default=False,
|
||||||
|
action='store_true',
|
||||||
|
help='list available programs and exit'
|
||||||
|
)
|
||||||
|
|
||||||
|
p_enable_output = parser.add_argument_group('enable output')
|
||||||
|
|
||||||
|
p_enable_output.add_argument(
|
||||||
|
'-o', '--stdout',
|
||||||
|
default=False,
|
||||||
|
action='store_true',
|
||||||
|
help=('write selected emoji to stdout, unless option "--nostdout" '
|
||||||
|
'is in effect')
|
||||||
|
)
|
||||||
|
|
||||||
|
p_enable_output.add_argument(
|
||||||
|
'-t', '--typing',
|
||||||
|
default=False,
|
||||||
|
action='store_true',
|
||||||
|
help=('simulate typing out the emoji on the keyboard, unless option '
|
||||||
|
'"--notyping" is in effect, typing can be unreliable and not '
|
||||||
|
'all applications may accept or play nice with it')
|
||||||
|
)
|
||||||
|
|
||||||
|
p_enable_output.add_argument(
|
||||||
|
'-c', '--clipboard',
|
||||||
|
default=False,
|
||||||
|
action='store_true',
|
||||||
|
help=('copy selected emoji to system clipboard, unless option '
|
||||||
|
'"--noclipboard" is in effect')
|
||||||
|
)
|
||||||
|
|
||||||
|
p_enable_output.add_argument(
|
||||||
|
'-n', '--notify',
|
||||||
|
default=False,
|
||||||
|
action='store_true',
|
||||||
|
help=('send selected emoji as a notification message, unless option '
|
||||||
|
'"--nonotify" is in effect')
|
||||||
|
)
|
||||||
|
|
||||||
|
p_disable_output = parser.add_argument_group('disable output')
|
||||||
|
|
||||||
|
p_disable_output.add_argument(
|
||||||
|
'-O', '--nostdout',
|
||||||
|
default=False,
|
||||||
|
action='store_true',
|
||||||
|
help='disable interaction with stdout, regardless of other options'
|
||||||
|
)
|
||||||
|
|
||||||
|
p_disable_output.add_argument(
|
||||||
|
'-T', '--notyping',
|
||||||
|
default=False,
|
||||||
|
action='store_true',
|
||||||
|
help=('disable simulated typing to active window, regardless of '
|
||||||
|
'other options')
|
||||||
|
)
|
||||||
|
|
||||||
|
p_disable_output.add_argument(
|
||||||
|
'-C', '--noclipboard',
|
||||||
|
default=False,
|
||||||
|
action='store_true',
|
||||||
|
help=('disable interaction with clipboard, regardless of other '
|
||||||
|
'options')
|
||||||
|
)
|
||||||
|
|
||||||
|
p_disable_output.add_argument(
|
||||||
|
'-N', '--nonotify',
|
||||||
|
default=False,
|
||||||
|
action='store_true',
|
||||||
|
help=('do not send any notification messages, regardless of other '
|
||||||
|
'options')
|
||||||
|
)
|
||||||
|
|
||||||
|
p_programs = parser.add_argument_group('programs')
|
||||||
|
|
||||||
|
p_programs.add_argument(
|
||||||
|
'--rofi',
|
||||||
|
metavar='CMD',
|
||||||
|
default='rofi',
|
||||||
|
help=('name or path to "rofi" program when option "--menu" is set to '
|
||||||
|
'"rofi"')
|
||||||
|
)
|
||||||
|
|
||||||
|
p_programs.add_argument(
|
||||||
|
'--dmenu',
|
||||||
|
metavar='CMD',
|
||||||
|
default='dmenu',
|
||||||
|
help=('name or path to "dmenu" program when option "--menu" is set to '
|
||||||
|
'"dmenu"')
|
||||||
|
)
|
||||||
|
|
||||||
|
p_programs.add_argument(
|
||||||
|
'--pmenu',
|
||||||
|
metavar='CMD',
|
||||||
|
default='pmenu',
|
||||||
|
help=('name or path to "pmenu" program when option "--menu" is set to '
|
||||||
|
'"pmenu"')
|
||||||
|
)
|
||||||
|
|
||||||
|
p_programs.add_argument(
|
||||||
|
'--fzf',
|
||||||
|
metavar='CMD',
|
||||||
|
default='fzf',
|
||||||
|
help=('name or path to "fzf" program when option "--menu" is set to '
|
||||||
|
'"fzf"')
|
||||||
|
)
|
||||||
|
|
||||||
|
p_programs.add_argument(
|
||||||
|
'--xclip',
|
||||||
|
metavar='CMD',
|
||||||
|
default='xclip',
|
||||||
|
help=('name or path to "xclip" program to handle clipboard when '
|
||||||
|
'option "--clipboard" is active')
|
||||||
|
)
|
||||||
|
|
||||||
|
p_programs.add_argument(
|
||||||
|
'--xdotool',
|
||||||
|
metavar='CMD',
|
||||||
|
default='xdotool',
|
||||||
|
help=('name or path to "xdotool" program to handle typing when option '
|
||||||
|
'"--typing" is active')
|
||||||
|
)
|
||||||
|
|
||||||
|
p_programs.add_argument(
|
||||||
|
'--notifysend',
|
||||||
|
metavar='CMD',
|
||||||
|
default='notify-send',
|
||||||
|
help=('name or path to "notify-send" program to handle notifications '
|
||||||
|
'when option "--notify" is active')
|
||||||
|
)
|
||||||
|
|
||||||
|
p_menufilter = parser.add_argument_group('engines and filters')
|
||||||
|
|
||||||
|
default_menu: str = 'rofi'
|
||||||
|
p_menufilter.add_argument(
|
||||||
|
'-M', '--menu',
|
||||||
|
metavar='SYSTEM',
|
||||||
|
default=default_menu,
|
||||||
|
choices=['rofi', 'dmenu', 'pmenu', 'fzf', 'filter', 'random', 'none'],
|
||||||
|
help=('change menu engine to select emojis, available systems: '
|
||||||
|
'"rofi", "dmenu", "pmenu", "fzf", "filter", "random", "none", '
|
||||||
|
'system "none" disables selection, "filter" won\'t display a '
|
||||||
|
'menu but choose first entry in the list that matches the text '
|
||||||
|
'at option "--pattern", systems "fzf" and "pmenu" are terminal '
|
||||||
|
'programs, "random" won\'t display a menu but choose an entry '
|
||||||
|
f'by random chance, defaults to: "{default_menu}"')
|
||||||
|
)
|
||||||
|
|
||||||
|
p_menufilter.add_argument(
|
||||||
|
'-p', '--pattern',
|
||||||
|
metavar='filter',
|
||||||
|
default='',
|
||||||
|
help=('simple text filter, used when option "--menu" is set to '
|
||||||
|
'"filter" or "fzf", causes in both cases to non interactive '
|
||||||
|
'selection of first emoji that matches the pattern')
|
||||||
|
)
|
||||||
|
|
||||||
|
default_matching_rofi: str = 'normal'
|
||||||
|
p_menufilter.add_argument(
|
||||||
|
'-m', '--matching-rofi',
|
||||||
|
metavar='MODE',
|
||||||
|
default=default_matching_rofi,
|
||||||
|
choices=['normal', 'regex', 'glob', 'fuzzy', 'prefix'],
|
||||||
|
help=('set matching algorithm for search in rofi, available modes: '
|
||||||
|
'"normal", "regex", "glob", "fuzzy", "prefix", defaults to: '
|
||||||
|
f'"{default_matching_rofi}"')
|
||||||
|
)
|
||||||
|
|
||||||
|
p_menufilter.add_argument(
|
||||||
|
'-i', '--ignore-case',
|
||||||
|
default=False,
|
||||||
|
action='store_true',
|
||||||
|
help=('ignore case sensitivity when searching list of emojis, '
|
||||||
|
'unless option "--noignore-case" is in effect')
|
||||||
|
)
|
||||||
|
|
||||||
|
p_menufilter.add_argument(
|
||||||
|
'-I', '--noignore-case',
|
||||||
|
default=False,
|
||||||
|
action='store_true',
|
||||||
|
help='case sensitive search of emojis, regardless of other options'
|
||||||
|
)
|
||||||
|
|
||||||
|
p_cache = parser.add_argument_group('cache files')
|
||||||
|
|
||||||
|
default_url = ('https://gist.githubusercontent.com/thingsiplay/'
|
||||||
|
'1f500459bc117cf0b63e1f5c11e03963/raw/'
|
||||||
|
'd8e4b78cfe66862cf3809443c1dba017f37b61db/emojis.json')
|
||||||
|
p_cache.add_argument(
|
||||||
|
'-u', '--url',
|
||||||
|
metavar='URL',
|
||||||
|
default=(default_url),
|
||||||
|
help=('source web address to download file "emojis.json", defaults '
|
||||||
|
f'to: "{default_url}"')
|
||||||
|
)
|
||||||
|
|
||||||
|
p_cache.add_argument(
|
||||||
|
'-U', '--offline',
|
||||||
|
default=False,
|
||||||
|
action='store_true',
|
||||||
|
help='prohibit downloading files from network, mainly "emojis.json"'
|
||||||
|
)
|
||||||
|
|
||||||
|
default_cache: str = "~/.cache/emojicherrypick"
|
||||||
|
p_cache.add_argument(
|
||||||
|
'-d', '--cache-dir',
|
||||||
|
metavar='DIR',
|
||||||
|
default=default_cache,
|
||||||
|
help=('directory for downloads and other long-lived temporary files '
|
||||||
|
f'used for quick access, defaults to: "{default_cache}"')
|
||||||
|
)
|
||||||
|
|
||||||
|
p_cache.add_argument(
|
||||||
|
'-w', '--wipe-cache',
|
||||||
|
default=False,
|
||||||
|
action='store_true',
|
||||||
|
help=('delete temporary cache files, redownload and recreate them '
|
||||||
|
'unless option "--offline" is in effect')
|
||||||
|
)
|
||||||
|
|
||||||
|
p_cache.add_argument(
|
||||||
|
'-E', '--noemojis',
|
||||||
|
default=False,
|
||||||
|
action='store_true',
|
||||||
|
help=('disable loading from main emojis database created from '
|
||||||
|
'"emojis.json"')
|
||||||
|
)
|
||||||
|
|
||||||
|
default_recents: str = "~/.cache/emojicherrypick/recents.cherry"
|
||||||
|
p_cache.add_argument(
|
||||||
|
'-r', '--recents',
|
||||||
|
metavar='FILE',
|
||||||
|
default=default_recents,
|
||||||
|
help=('program keeps track of last used emojis and saves them to '
|
||||||
|
'a history file, the last entries will be displayed at the top '
|
||||||
|
'of each emoji listing in the menus, same format as '
|
||||||
|
'"--favorites" file, use option "--recents-size" to set number '
|
||||||
|
f'of entries to show blah, defaults to: "{default_recents}"')
|
||||||
|
)
|
||||||
|
|
||||||
|
p_cache.add_argument(
|
||||||
|
'-R', '--norecents',
|
||||||
|
default=False,
|
||||||
|
action='store_true',
|
||||||
|
help='disable recents file specified at option "--recents"'
|
||||||
|
)
|
||||||
|
|
||||||
|
default_recents_size: int = 2
|
||||||
|
p_cache.add_argument(
|
||||||
|
'-k', '--recents-size',
|
||||||
|
metavar='NUM',
|
||||||
|
default=default_recents_size,
|
||||||
|
type=int,
|
||||||
|
choices=range(0, 200),
|
||||||
|
help=('read number of recently used emojis and ignore rest of file, '
|
||||||
|
'can be used for displaying in the menu or at filters, '
|
||||||
|
f'defaults to: "{default_recents_size}"')
|
||||||
|
)
|
||||||
|
|
||||||
|
p_cache.add_argument(
|
||||||
|
'--ignore-skin',
|
||||||
|
default=True,
|
||||||
|
action=argparse.BooleanOptionalAction,
|
||||||
|
help='ignore emoji skin variations when creating the cache'
|
||||||
|
)
|
||||||
|
|
||||||
|
p_config = parser.add_argument_group('config files')
|
||||||
|
|
||||||
|
default_favorites: str = "~/.config/emojicherrypick/favorites.cherry"
|
||||||
|
p_config.add_argument(
|
||||||
|
'-f', '--favorites',
|
||||||
|
metavar='FILE',
|
||||||
|
default=default_favorites,
|
||||||
|
help=('user list of emojis to list at the beginning of each emoji '
|
||||||
|
'listing in the menus, 1 line per emoji set, each set starts '
|
||||||
|
'with an emoji or any text and goes until first space is found, '
|
||||||
|
'rest of the line are names, descripion and keywords, defaults '
|
||||||
|
f'to: "{default_favorites}"')
|
||||||
|
)
|
||||||
|
|
||||||
|
p_config.add_argument(
|
||||||
|
'-F', '--nofavorites',
|
||||||
|
default=False,
|
||||||
|
action='store_true',
|
||||||
|
help='disable favorites file specified at option "--favorites"'
|
||||||
|
)
|
||||||
|
|
||||||
|
p_menuinterface = parser.add_argument_group('menu interface')
|
||||||
|
|
||||||
|
default_prompt: str = '🍒'
|
||||||
|
p_menuinterface.add_argument(
|
||||||
|
'-@', '--prompt',
|
||||||
|
metavar='TEXT',
|
||||||
|
default=default_prompt,
|
||||||
|
help=('set custom prompt on user input menu left of entry field, '
|
||||||
|
f'defaults to: "{default_prompt}"')
|
||||||
|
)
|
||||||
|
|
||||||
|
default_font_family: str = 'Noto Color Emoji'
|
||||||
|
p_menuinterface.add_argument(
|
||||||
|
'-g', '--font-family',
|
||||||
|
metavar='NAME',
|
||||||
|
default=default_font_family,
|
||||||
|
help=('font name to use for dispaly with the menu, defaults to: '
|
||||||
|
f'"{default_font_family}"')
|
||||||
|
)
|
||||||
|
|
||||||
|
default_font_size: int = 16
|
||||||
|
p_menuinterface.add_argument(
|
||||||
|
'-s', '--font-size',
|
||||||
|
metavar='NUM',
|
||||||
|
default=default_font_size,
|
||||||
|
type=int,
|
||||||
|
choices=range(4, 256),
|
||||||
|
help=('font size of emojis and text to display in the menu, '
|
||||||
|
f'defaults to: "{default_font_size}"')
|
||||||
|
)
|
||||||
|
|
||||||
|
default_list_size: int = 15
|
||||||
|
p_menuinterface.add_argument(
|
||||||
|
'-l', '--list-size',
|
||||||
|
metavar='NUM',
|
||||||
|
default=default_list_size,
|
||||||
|
type=int,
|
||||||
|
choices=range(1, 200),
|
||||||
|
help=('number of rows to display in the menu, defaults to: '
|
||||||
|
f'"{default_list_size}"')
|
||||||
|
)
|
||||||
|
|
||||||
|
if args is None:
|
||||||
|
return parser.parse_args()
|
||||||
|
else:
|
||||||
|
return parser.parse_args(args)
|
||||||
|
|
||||||
|
|
||||||
|
def main(args: list[str] | None = None) -> int:
|
||||||
|
""" Run the application. """
|
||||||
|
|
||||||
|
app: App
|
||||||
|
if not args and not sys.argv[1:]:
|
||||||
|
args_default: list[str] = [os.getenv('EMOJICHERRYPICK_DEFAULT',
|
||||||
|
default='-con')]
|
||||||
|
app = App(parse_arguments(args_default))
|
||||||
|
else:
|
||||||
|
app = App(parse_arguments(args))
|
||||||
|
|
||||||
|
if app.list_version:
|
||||||
|
app.print_version()
|
||||||
|
return 0
|
||||||
|
elif app.list_programs:
|
||||||
|
app.print_list_programs()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
if app.menu == 'rofi':
|
||||||
|
app.select_by_rofi()
|
||||||
|
elif app.menu == 'dmenu':
|
||||||
|
app.select_by_dmenu()
|
||||||
|
elif app.menu == 'pmenu':
|
||||||
|
app.select_by_pmenu()
|
||||||
|
elif app.menu == 'fzf':
|
||||||
|
app.select_by_fzf()
|
||||||
|
elif app.menu == 'filter':
|
||||||
|
app.select_by_filter()
|
||||||
|
elif app.menu == 'random':
|
||||||
|
app.select_by_random()
|
||||||
|
elif app.menu == 'none':
|
||||||
|
app.select_by_none()
|
||||||
|
else:
|
||||||
|
raise RuntimeError('Unkown menu option.')
|
||||||
|
return -1
|
||||||
|
except subprocess.SubprocessError:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if app.selected_emoji:
|
||||||
|
try:
|
||||||
|
if app.stdout:
|
||||||
|
app.send_emoji_to_stdout()
|
||||||
|
if app.clipboard:
|
||||||
|
app.send_emoji_to_clipboard()
|
||||||
|
if app.typing:
|
||||||
|
app.send_emoji_to_typing()
|
||||||
|
if app.notify:
|
||||||
|
app.send_emoji_to_notify()
|
||||||
|
except subprocess.SubprocessError:
|
||||||
|
return 3
|
||||||
|
elif app.menu == 'none':
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
return 2
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main())
|
||||||
14
home/.local/usr/bin/foot-smart
Executable file
14
home/.local/usr/bin/foot-smart
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
if footclient "$@" 2>/dev/null; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec foot --server &
|
||||||
|
|
||||||
|
sleep 0.2
|
||||||
|
|
||||||
|
exec footclient "$@" || {
|
||||||
|
echo "Failed to connect to foot server." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
329
home/.local/usr/bin/fzf-git.sh
Executable file
329
home/.local/usr/bin/fzf-git.sh
Executable file
@@ -0,0 +1,329 @@
|
|||||||
|
# The MIT License (MIT)
|
||||||
|
#
|
||||||
|
# Copyright (c) 2024 Junegunn Choi
|
||||||
|
#
|
||||||
|
# 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, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# shellcheck disable=SC2039
|
||||||
|
[[ $0 = - ]] && return
|
||||||
|
|
||||||
|
__fzf_git_color() {
|
||||||
|
if [[ -n $NO_COLOR ]]; then
|
||||||
|
echo never
|
||||||
|
elif [[ $# -gt 0 ]] && [[ -n $FZF_GIT_PREVIEW_COLOR ]]; then
|
||||||
|
echo "$FZF_GIT_PREVIEW_COLOR"
|
||||||
|
else
|
||||||
|
echo "${FZF_GIT_COLOR:-always}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
__fzf_git_cat() {
|
||||||
|
if [[ -n $FZF_GIT_CAT ]]; then
|
||||||
|
echo "$FZF_GIT_CAT"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Sometimes bat is installed as batcat
|
||||||
|
_fzf_git_bat_options="--style='${BAT_STYLE:-full}' --color=$(__fzf_git_color .) --pager=never"
|
||||||
|
if command -v batcat > /dev/null; then
|
||||||
|
echo "batcat $_fzf_git_bat_options"
|
||||||
|
elif command -v bat > /dev/null; then
|
||||||
|
echo "bat $_fzf_git_bat_options"
|
||||||
|
else
|
||||||
|
echo cat
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
__fzf_git_pager() {
|
||||||
|
local pager
|
||||||
|
pager="${FZF_GIT_PAGER:-${GIT_PAGER:-$(git config --get core.pager 2>/dev/null)}}"
|
||||||
|
echo "${pager:-cat}"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ $# -eq 1 ]]; then
|
||||||
|
branches() {
|
||||||
|
git branch "$@" --sort=-committerdate --sort=-HEAD --format=$'%(HEAD) %(color:yellow)%(refname:short) %(color:green)(%(committerdate:relative))\t%(color:blue)%(subject)%(color:reset)' --color=$(__fzf_git_color) | column -ts$'\t'
|
||||||
|
}
|
||||||
|
refs() {
|
||||||
|
git for-each-ref "$@" --sort=-creatordate --sort=-HEAD --color=$(__fzf_git_color) --format=$'%(if:equals=refs/remotes)%(refname:rstrip=-2)%(then)%(color:magenta)remote-branch%(else)%(if:equals=refs/heads)%(refname:rstrip=-2)%(then)%(color:brightgreen)branch%(else)%(if:equals=refs/tags)%(refname:rstrip=-2)%(then)%(color:brightcyan)tag%(else)%(if:equals=refs/stash)%(refname:rstrip=-2)%(then)%(color:brightred)stash%(else)%(color:white)%(refname:rstrip=-2)%(end)%(end)%(end)%(end)\t%(color:yellow)%(refname:short) %(color:green)(%(creatordate:relative))\t%(color:blue)%(subject)%(color:reset)' | column -ts$'\t'
|
||||||
|
}
|
||||||
|
hashes() {
|
||||||
|
git log --date=short --format="%C(green)%C(bold)%cd %C(auto)%h%d %s (%an)" --graph --color=$(__fzf_git_color) "$@"
|
||||||
|
}
|
||||||
|
case "$1" in
|
||||||
|
branches)
|
||||||
|
echo $'CTRL-O (open in browser) ╱ ALT-A (show all branches)\n'
|
||||||
|
branches
|
||||||
|
;;
|
||||||
|
all-branches)
|
||||||
|
echo $'CTRL-O (open in browser)\n'
|
||||||
|
branches -a
|
||||||
|
;;
|
||||||
|
hashes)
|
||||||
|
echo $'CTRL-O (open in browser) ╱ CTRL-D (diff)\nCTRL-S (toggle sort) ╱ ALT-A (show all hashes)\n'
|
||||||
|
hashes
|
||||||
|
;;
|
||||||
|
all-hashes)
|
||||||
|
echo $'CTRL-O (open in browser) ╱ CTRL-D (diff)\nCTRL-S (toggle sort)\n'
|
||||||
|
hashes --all
|
||||||
|
;;
|
||||||
|
refs)
|
||||||
|
echo $'CTRL-O (open in browser) ╱ ALT-E (examine in editor) ╱ ALT-A (show all refs)\n'
|
||||||
|
refs --exclude='refs/remotes'
|
||||||
|
;;
|
||||||
|
all-refs)
|
||||||
|
echo $'CTRL-O (open in browser) ╱ ALT-E (examine in editor)\n'
|
||||||
|
refs
|
||||||
|
;;
|
||||||
|
nobeep) ;;
|
||||||
|
*) exit 1 ;;
|
||||||
|
esac
|
||||||
|
elif [[ $# -gt 1 ]]; then
|
||||||
|
set -e
|
||||||
|
|
||||||
|
branch=$(git rev-parse --abbrev-ref HEAD 2> /dev/null)
|
||||||
|
if [[ $branch = HEAD ]]; then
|
||||||
|
branch=$(git describe --exact-match --tags 2> /dev/null || git rev-parse --short HEAD)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Only supports GitHub for now
|
||||||
|
case "$1" in
|
||||||
|
commit)
|
||||||
|
hash=$(grep -o "[a-f0-9]\{7,\}" <<< "$2")
|
||||||
|
path=/commit/$hash
|
||||||
|
;;
|
||||||
|
branch|remote-branch)
|
||||||
|
branch=$(sed 's/^[* ]*//' <<< "$2" | cut -d' ' -f1)
|
||||||
|
remote=$(git config branch."${branch}".remote || echo 'origin')
|
||||||
|
branch=${branch#$remote/}
|
||||||
|
path=/tree/$branch
|
||||||
|
;;
|
||||||
|
remote)
|
||||||
|
remote=$2
|
||||||
|
path=/tree/$branch
|
||||||
|
;;
|
||||||
|
file) path=/blob/$branch/$(git rev-parse --show-prefix)$2 ;;
|
||||||
|
tag) path=/releases/tag/$2 ;;
|
||||||
|
*) exit 1 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
remote=${remote:-$(git config branch."${branch}".remote || echo 'origin')}
|
||||||
|
remote_url=$(git remote get-url "$remote" 2> /dev/null || echo "$remote")
|
||||||
|
|
||||||
|
if [[ $remote_url =~ ^git@ ]]; then
|
||||||
|
url=${remote_url%.git}
|
||||||
|
url=${url#git@}
|
||||||
|
url=https://${url/://}
|
||||||
|
elif [[ $remote_url =~ ^http ]]; then
|
||||||
|
url=${remote_url%.git}
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$(uname -s)" in
|
||||||
|
Darwin) open "$url$path" ;;
|
||||||
|
*) xdg-open "$url$path" ;;
|
||||||
|
esac
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $- =~ i ]]; then
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Redefine this function to change the options
|
||||||
|
_fzf_git_fzf() {
|
||||||
|
fzf --height=50% --tmux 90%,70% \
|
||||||
|
--layout=reverse --multi --min-height=20 --border \
|
||||||
|
--border-label-pos=2 \
|
||||||
|
--color='header:italic:underline,label:blue' \
|
||||||
|
--preview-window='right,50%,border-left' \
|
||||||
|
--bind='ctrl-/:change-preview-window(down,50%,border-top|hidden|)' "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
_fzf_git_check() {
|
||||||
|
git rev-parse HEAD > /dev/null 2>&1 && return
|
||||||
|
|
||||||
|
[[ -n $TMUX ]] && tmux display-message "Not in a git repository"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
__fzf_git=${BASH_SOURCE[0]:-${(%):-%x}}
|
||||||
|
__fzf_git=$(readlink -f "$__fzf_git" 2> /dev/null || /usr/bin/ruby --disable-gems -e 'puts File.expand_path(ARGV.first)' "$__fzf_git" 2> /dev/null)
|
||||||
|
|
||||||
|
_fzf_git_files() {
|
||||||
|
_fzf_git_check || return
|
||||||
|
local root query
|
||||||
|
root=$(git rev-parse --show-toplevel)
|
||||||
|
[[ $root != "$PWD" ]] && query='!../ '
|
||||||
|
|
||||||
|
(git -c color.status=$(__fzf_git_color) status --short --no-branch
|
||||||
|
git ls-files "$root" | grep -vxFf <(git status -s | grep '^[^?]' | cut -c4-; echo :) | sed 's/^/ /') |
|
||||||
|
_fzf_git_fzf -m --ansi --nth 2..,.. \
|
||||||
|
--border-label '📁 Files' \
|
||||||
|
--header $'CTRL-O (open in browser) ╱ ALT-E (open in editor)\n\n' \
|
||||||
|
--bind "ctrl-o:execute-silent:bash $__fzf_git file {-1}" \
|
||||||
|
--bind "alt-e:execute:${EDITOR:-vim} {-1} > /dev/tty" \
|
||||||
|
--query "$query" \
|
||||||
|
--preview "git diff --no-ext-diff --color=$(__fzf_git_color .) -- {-1} | $(__fzf_git_pager); $(__fzf_git_cat) {-1}" "$@" |
|
||||||
|
cut -c4- | sed 's/.* -> //'
|
||||||
|
}
|
||||||
|
|
||||||
|
_fzf_git_branches() {
|
||||||
|
_fzf_git_check || return
|
||||||
|
bash "$__fzf_git" branches |
|
||||||
|
_fzf_git_fzf --ansi \
|
||||||
|
--border-label '🌲 Branches' \
|
||||||
|
--header-lines 2 \
|
||||||
|
--tiebreak begin \
|
||||||
|
--preview-window down,border-top,40% \
|
||||||
|
--color hl:underline,hl+:underline \
|
||||||
|
--no-hscroll \
|
||||||
|
--bind 'ctrl-/:change-preview-window(down,70%|hidden|)' \
|
||||||
|
--bind "ctrl-o:execute-silent:bash $__fzf_git branch {}" \
|
||||||
|
--bind "alt-a:change-border-label(🌳 All branches)+reload:bash \"$__fzf_git\" all-branches" \
|
||||||
|
--preview "git log --oneline --graph --date=short --color=$(__fzf_git_color .) --pretty='format:%C(auto)%cd %h%d %s' \$(sed s/^..// <<< {} | cut -d' ' -f1) --" "$@" |
|
||||||
|
sed 's/^..//' | cut -d' ' -f1
|
||||||
|
}
|
||||||
|
|
||||||
|
_fzf_git_tags() {
|
||||||
|
_fzf_git_check || return
|
||||||
|
git tag --sort -version:refname |
|
||||||
|
_fzf_git_fzf --preview-window right,70% \
|
||||||
|
--border-label '📛 Tags' \
|
||||||
|
--header $'CTRL-O (open in browser)\n\n' \
|
||||||
|
--bind "ctrl-o:execute-silent:bash $__fzf_git tag {}" \
|
||||||
|
--preview "git show --color=$(__fzf_git_color .) {} | $(__fzf_git_pager)" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
_fzf_git_hashes() {
|
||||||
|
_fzf_git_check || return
|
||||||
|
bash "$__fzf_git" hashes |
|
||||||
|
_fzf_git_fzf --ansi --no-sort --bind 'ctrl-s:toggle-sort' \
|
||||||
|
--border-label '🍡 Hashes' \
|
||||||
|
--header-lines 3 \
|
||||||
|
--bind "ctrl-o:execute-silent:bash $__fzf_git commit {}" \
|
||||||
|
--bind "ctrl-d:execute:grep -o '[a-f0-9]\{7,\}' <<< {} | head -n 1 | xargs git diff --color=$(__fzf_git_color) > /dev/tty" \
|
||||||
|
--bind "alt-a:change-border-label(🍇 All hashes)+reload:bash \"$__fzf_git\" all-hashes" \
|
||||||
|
--color hl:underline,hl+:underline \
|
||||||
|
--preview "grep -o '[a-f0-9]\{7,\}' <<< {} | head -n 1 | xargs git show --color=$(__fzf_git_color .) | $(__fzf_git_pager)" "$@" |
|
||||||
|
awk 'match($0, /[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]*/) { print substr($0, RSTART, RLENGTH) }'
|
||||||
|
}
|
||||||
|
|
||||||
|
_fzf_git_remotes() {
|
||||||
|
_fzf_git_check || return
|
||||||
|
git remote -v | awk '{print $1 "\t" $2}' | uniq |
|
||||||
|
_fzf_git_fzf --tac \
|
||||||
|
--border-label '📡 Remotes' \
|
||||||
|
--header $'CTRL-O (open in browser)\n\n' \
|
||||||
|
--bind "ctrl-o:execute-silent:bash $__fzf_git remote {1}" \
|
||||||
|
--preview-window right,70% \
|
||||||
|
--preview "git log --oneline --graph --date=short --color=$(__fzf_git_color .) --pretty='format:%C(auto)%cd %h%d %s' '{1}/$(git rev-parse --abbrev-ref HEAD)' --" "$@" |
|
||||||
|
cut -d$'\t' -f1
|
||||||
|
}
|
||||||
|
|
||||||
|
_fzf_git_stashes() {
|
||||||
|
_fzf_git_check || return
|
||||||
|
git stash list | _fzf_git_fzf \
|
||||||
|
--border-label '🥡 Stashes' \
|
||||||
|
--header $'CTRL-X (drop stash)\n\n' \
|
||||||
|
--bind 'ctrl-x:reload(git stash drop -q {1}; git stash list)' \
|
||||||
|
-d: --preview "git show --color=$(__fzf_git_color .) {1} | $(__fzf_git_pager)" "$@" |
|
||||||
|
cut -d: -f1
|
||||||
|
}
|
||||||
|
|
||||||
|
_fzf_git_lreflogs() {
|
||||||
|
_fzf_git_check || return
|
||||||
|
git reflog --color=$(__fzf_git_color) --format="%C(blue)%gD %C(yellow)%h%C(auto)%d %gs" | _fzf_git_fzf --ansi \
|
||||||
|
--border-label '📒 Reflogs' \
|
||||||
|
--preview "git show --color=$(__fzf_git_color .) {1} | $(__fzf_git_pager)" "$@" |
|
||||||
|
awk '{print $1}'
|
||||||
|
}
|
||||||
|
|
||||||
|
_fzf_git_each_ref() {
|
||||||
|
_fzf_git_check || return
|
||||||
|
bash "$__fzf_git" refs | _fzf_git_fzf --ansi \
|
||||||
|
--nth 2,2.. \
|
||||||
|
--tiebreak begin \
|
||||||
|
--border-label '☘️ Each ref' \
|
||||||
|
--header-lines 2 \
|
||||||
|
--preview-window down,border-top,40% \
|
||||||
|
--color hl:underline,hl+:underline \
|
||||||
|
--no-hscroll \
|
||||||
|
--bind 'ctrl-/:change-preview-window(down,70%|hidden|)' \
|
||||||
|
--bind "ctrl-o:execute-silent:bash $__fzf_git {1} {2}" \
|
||||||
|
--bind "alt-e:execute:${EDITOR:-vim} <(git show {2}) > /dev/tty" \
|
||||||
|
--bind "alt-a:change-border-label(🍀 Every ref)+reload:bash \"$__fzf_git\" all-refs" \
|
||||||
|
--preview "git log --oneline --graph --date=short --color=$(__fzf_git_color .) --pretty='format:%C(auto)%cd %h%d %s' {2} --" "$@" |
|
||||||
|
awk '{print $2}'
|
||||||
|
}
|
||||||
|
|
||||||
|
_fzf_git_worktrees() {
|
||||||
|
_fzf_git_check || return
|
||||||
|
git worktree list | _fzf_git_fzf \
|
||||||
|
--border-label '🌴 Worktrees' \
|
||||||
|
--header $'CTRL-X (remove worktree)\n\n' \
|
||||||
|
--bind 'ctrl-x:reload(git worktree remove {1} > /dev/null; git worktree list)' \
|
||||||
|
--preview "
|
||||||
|
git -c color.status=$(__fzf_git_color .) -C {1} status --short --branch
|
||||||
|
echo
|
||||||
|
git log --oneline --graph --date=short --color=$(__fzf_git_color .) --pretty='format:%C(auto)%cd %h%d %s' {2} --
|
||||||
|
" "$@" |
|
||||||
|
awk '{print $1}'
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ -n "${BASH_VERSION:-}" ]]; then
|
||||||
|
__fzf_git_init() {
|
||||||
|
bind -m emacs-standard '"\er": redraw-current-line'
|
||||||
|
bind -m emacs-standard '"\C-z": vi-editing-mode'
|
||||||
|
bind -m vi-command '"\C-z": emacs-editing-mode'
|
||||||
|
bind -m vi-insert '"\C-z": emacs-editing-mode'
|
||||||
|
|
||||||
|
local o c
|
||||||
|
for o in "$@"; do
|
||||||
|
c=${o:0:1}
|
||||||
|
bind -m emacs-standard '"\C-g\C-'$c'": " \C-u \C-a\C-k`_fzf_git_'$o'`\e\C-e\C-y\C-a\C-y\ey\C-h\C-e\er \C-h"'
|
||||||
|
bind -m vi-command '"\C-g\C-'$c'": "\C-z\C-g\C-'$c'\C-z"'
|
||||||
|
bind -m vi-insert '"\C-g\C-'$c'": "\C-z\C-g\C-'$c'\C-z"'
|
||||||
|
bind -m emacs-standard '"\C-g'$c'": " \C-u \C-a\C-k`_fzf_git_'$o'`\e\C-e\C-y\C-a\C-y\ey\C-h\C-e\er \C-h"'
|
||||||
|
bind -m vi-command '"\C-g'$c'": "\C-z\C-g'$c'\C-z"'
|
||||||
|
bind -m vi-insert '"\C-g'$c'": "\C-z\C-g'$c'\C-z"'
|
||||||
|
done
|
||||||
|
}
|
||||||
|
elif [[ -n "${ZSH_VERSION:-}" ]]; then
|
||||||
|
__fzf_git_join() {
|
||||||
|
local item
|
||||||
|
while read item; do
|
||||||
|
echo -n "${(q)item} "
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
__fzf_git_init() {
|
||||||
|
local m o
|
||||||
|
for o in "$@"; do
|
||||||
|
eval "fzf-git-$o-widget() { local result=\$(_fzf_git_$o | __fzf_git_join); zle reset-prompt; LBUFFER+=\$result }"
|
||||||
|
eval "zle -N fzf-git-$o-widget"
|
||||||
|
for m in emacs vicmd viins; do
|
||||||
|
eval "bindkey -M $m '^g^${o[1]}' fzf-git-$o-widget"
|
||||||
|
eval "bindkey -M $m '^g${o[1]}' fzf-git-$o-widget"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
__fzf_git_init files branches tags remotes hashes stashes lreflogs each_ref worktrees
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
fi
|
||||||
1
home/.local/usr/bin/getMusic
Executable file
1
home/.local/usr/bin/getMusic
Executable file
@@ -0,0 +1 @@
|
|||||||
|
#!/usr/env python
|
||||||
3
home/.local/usr/bin/gettmuxLayout
Executable file
3
home/.local/usr/bin/gettmuxLayout
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/bin/bash
|
||||||
|
layout=$( tmux display-message -p "#{window_layout}" )
|
||||||
|
echo $layout
|
||||||
16
home/.local/usr/bin/igrep
Executable file
16
home/.local/usr/bin/igrep
Executable file
@@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Check if the first argument is a path and assign it to SEARCH_PATH
|
||||||
|
SEARCH_PATH="${1:-.}"
|
||||||
|
|
||||||
|
# Shift the arguments so any additional arguments are treated as the search pattern for `rg`
|
||||||
|
shift
|
||||||
|
|
||||||
|
# Execute `rg` in the specified path with the search pattern
|
||||||
|
rg --color=always --line-number --no-heading --smart-case --hidden "${*:-}" "$SEARCH_PATH" |
|
||||||
|
fzf --ansi \
|
||||||
|
--color "hl:-1:underline,hl+:-1:underline:reverse" \
|
||||||
|
--delimiter : \
|
||||||
|
--preview 'bat --color=always {1} --highlight-line {2}' \
|
||||||
|
--preview-window 'up,60%,border-bottom,+{2}+3/3,~3' \
|
||||||
|
--bind 'enter:become(nvim {1} +{2})'
|
||||||
9
home/.local/usr/bin/inotify_test_pytest.sh
Executable file
9
home/.local/usr/bin/inotify_test_pytest.sh
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
inotifywait -e modify,create,delete -r ./src ./tests/
|
||||||
|
clear
|
||||||
|
echo "File change detected. Running tests..."
|
||||||
|
pytest -s
|
||||||
|
echo "Waiting for changes..."
|
||||||
|
done
|
||||||
9
home/.local/usr/bin/inotify_test_rust.sh
Executable file
9
home/.local/usr/bin/inotify_test_rust.sh
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
inotifywait -e modify,create,delete -r ./src/
|
||||||
|
clear
|
||||||
|
echo "File change detected. Running build..."
|
||||||
|
cargo build
|
||||||
|
echo "Waiting for changes..."
|
||||||
|
done
|
||||||
9
home/.local/usr/bin/inotify_test_zig.sh
Executable file
9
home/.local/usr/bin/inotify_test_zig.sh
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
inotifywait -e modify,create,delete -r ./build.zig ./build.zig.zon ./src/*
|
||||||
|
clear
|
||||||
|
echo "File change detected. Running tests..."
|
||||||
|
zig build run
|
||||||
|
echo "Waiting for changes..."
|
||||||
|
done
|
||||||
3
home/.local/usr/bin/nestX
Executable file
3
home/.local/usr/bin/nestX
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
Xephyr -br -ac -noreset -screen 1366x768 :1
|
||||||
10
home/.local/usr/bin/popuptmux
Executable file
10
home/.local/usr/bin/popuptmux
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
width=${2:-100%}
|
||||||
|
# width=${2:-80%}
|
||||||
|
height=${2:-30%}
|
||||||
|
if [ "$(tmux display-message -p -F "#{session_name}")" = "popup" ];then
|
||||||
|
tmux detach-client
|
||||||
|
else
|
||||||
|
tmux popup -d '#{pane_current_path}' -xC -y1 -w$width -h$height -E "tmux attach -t popup || tmux new -s popup"
|
||||||
|
# tmux popup -d '#{pane_current_path}' -xC -yC -w$width -h$height -E "tmux attach -t popup || tmux new -s popup"
|
||||||
|
fi
|
||||||
25
home/.local/usr/bin/project-picker.sh
Executable file
25
home/.local/usr/bin/project-picker.sh
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Set the directory where your projects are located
|
||||||
|
PROJECTS_DIR="${HOME}/Projects/"
|
||||||
|
|
||||||
|
# Use fzf to select a directory
|
||||||
|
folder=$(find "$PROJECTS_DIR" -type d -maxdepth 1 | \
|
||||||
|
fzf --delimiter / --with-nth=-1 --keep-right \
|
||||||
|
--prompt="Projects " \
|
||||||
|
--tmux left,40 --reverse \
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check if a directory was selected
|
||||||
|
if [[ -n "$folder" ]]; then
|
||||||
|
projectname="${folder##*/}"
|
||||||
|
# Check if a tmux window with the project name already exists
|
||||||
|
if tmux list-windows -F "#{window_name}" | grep -q "^$projectname$"; then
|
||||||
|
tmux select-window -t "$projectname"
|
||||||
|
else
|
||||||
|
# Create a new tmux window with the project name and open nvim in the folder
|
||||||
|
# tmux new-window -n "$projectname" "cd '$folder' &&"
|
||||||
|
tmux new-window -n "$projectname" "cd '$folder' && nvim"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
BIN
home/.local/usr/bin/pytui
Executable file
BIN
home/.local/usr/bin/pytui
Executable file
Binary file not shown.
304
home/.local/usr/bin/qute-pass
Executable file
304
home/.local/usr/bin/qute-pass
Executable file
@@ -0,0 +1,304 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: Chris Braun (cryzed) <cryzed@googlemail.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
"""
|
||||||
|
Insert login information using pass and a dmenu-compatible application (e.g. dmenu, rofi -dmenu, ...). A short
|
||||||
|
demonstration can be seen here: https://i.imgur.com/KN3XuZP.gif.
|
||||||
|
"""
|
||||||
|
|
||||||
|
USAGE = """The domain of the site has to appear as a segment in the pass path,
|
||||||
|
for example: "github.com/cryzed" or "websites/github.com". Alternatively the
|
||||||
|
parameter `--unfiltered` may be used to get a list of all passwords. How the
|
||||||
|
username and password are determined is freely configurable using the CLI
|
||||||
|
arguments. As an example, if you instead store the username as part of the
|
||||||
|
secret (and use a site's name as filename), instead of the default configuration,
|
||||||
|
use `--username-target secret` and `--username-pattern "username: (.+)"`.
|
||||||
|
|
||||||
|
The login information is inserted by emulating key events using qutebrowser's
|
||||||
|
fake-key command in this manner: [USERNAME]<Tab>[PASSWORD], which is compatible
|
||||||
|
with almost all login forms.
|
||||||
|
|
||||||
|
If you use gopass with multiple mounts, use the CLI switch --mode gopass to switch to gopass mode.
|
||||||
|
|
||||||
|
Suggested bindings similar to Uzbl's `formfiller` script:
|
||||||
|
|
||||||
|
config.bind('<z><l>', 'spawn --userscript qute-pass')
|
||||||
|
config.bind('<z><u><l>', 'spawn --userscript qute-pass --username-only')
|
||||||
|
config.bind('<z><p><l>', 'spawn --userscript qute-pass --password-only')
|
||||||
|
config.bind('<z><o><l>', 'spawn --userscript qute-pass --otp-only')
|
||||||
|
"""
|
||||||
|
|
||||||
|
EPILOG = """Dependencies: tldextract (Python 3 module), pass, pass-otp (optional).
|
||||||
|
|
||||||
|
WARNING: The login details are viewable as plaintext in qutebrowser's debug log (qute://log) and might be shared if
|
||||||
|
you decide to submit a crash report!"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import enum
|
||||||
|
import fnmatch
|
||||||
|
import functools
|
||||||
|
import idna
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import shlex
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import unicodedata
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
|
import tldextract
|
||||||
|
|
||||||
|
|
||||||
|
def expanded_path(path):
|
||||||
|
# Expand potential ~ in paths, since this script won't be called from a shell that does it for us
|
||||||
|
expanded = os.path.expanduser(path)
|
||||||
|
# Add trailing slash if not present
|
||||||
|
return os.path.join(expanded, '')
|
||||||
|
|
||||||
|
|
||||||
|
argument_parser = argparse.ArgumentParser(description=__doc__, usage=USAGE, epilog=EPILOG)
|
||||||
|
argument_parser.add_argument('url', nargs='?', default=os.getenv('QUTE_URL'))
|
||||||
|
argument_parser.add_argument('--password-store', '-p',
|
||||||
|
default=expanded_path(os.getenv('PASSWORD_STORE_DIR', default='~/.password-store')),
|
||||||
|
help='Path to your pass password-store (only used in pass-mode)', type=expanded_path)
|
||||||
|
argument_parser.add_argument('--mode', '-M', choices=['pass', 'gopass'], default="pass",
|
||||||
|
help='Select mode [gopass] to use gopass instead of the standard pass.')
|
||||||
|
argument_parser.add_argument('--prefix', type=str,
|
||||||
|
help='Search only the given subfolder of the store (only used in gopass-mode)')
|
||||||
|
argument_parser.add_argument('--username-pattern', '-u', default=r'.*/(.+)',
|
||||||
|
help='Regular expression that matches the username')
|
||||||
|
argument_parser.add_argument('--username-target', '-U', choices=['path', 'secret'], default='path',
|
||||||
|
help='The target for the username regular expression')
|
||||||
|
argument_parser.add_argument('--password-pattern', '-P', default=r'(.*)',
|
||||||
|
help='Regular expression that matches the password')
|
||||||
|
argument_parser.add_argument('--dmenu-invocation', '-d', default='rofi -dmenu',
|
||||||
|
help='Invocation used to execute a dmenu-provider')
|
||||||
|
argument_parser.add_argument('--no-insert-mode', '-n', dest='insert_mode', action='store_false',
|
||||||
|
help="Don't automatically enter insert mode")
|
||||||
|
argument_parser.add_argument('--io-encoding', '-i', default='UTF-8',
|
||||||
|
help='Encoding used to communicate with subprocesses')
|
||||||
|
argument_parser.add_argument('--merge-candidates', '-m', action='store_true',
|
||||||
|
help='Merge pass candidates for fully-qualified and registered domain name')
|
||||||
|
argument_parser.add_argument('--extra-url-suffixes', '-s', default='',
|
||||||
|
help='Comma-separated string containing extra suffixes (e.g local)')
|
||||||
|
argument_parser.add_argument('--unfiltered', dest='unfiltered', action='store_true',
|
||||||
|
help='Show an unfiltered selection of all passwords in the store')
|
||||||
|
argument_parser.add_argument('--always-show-selection', dest='always_show_selection', action='store_true',
|
||||||
|
help='Always show selection, even if there is only a single match')
|
||||||
|
group = argument_parser.add_mutually_exclusive_group()
|
||||||
|
group.add_argument('--username-only', '-e', action='store_true', help='Only insert username')
|
||||||
|
group.add_argument('--password-only', '-w', action='store_true', help='Only insert password')
|
||||||
|
group.add_argument('--otp-only', '-o', action='store_true', help='Only insert OTP code')
|
||||||
|
|
||||||
|
stderr = functools.partial(print, file=sys.stderr)
|
||||||
|
|
||||||
|
|
||||||
|
class ExitCodes(enum.IntEnum):
|
||||||
|
SUCCESS = 0
|
||||||
|
FAILURE = 1
|
||||||
|
# 1 is automatically used if Python throws an exception
|
||||||
|
NO_PASS_CANDIDATES = 2
|
||||||
|
COULD_NOT_MATCH_USERNAME = 3
|
||||||
|
COULD_NOT_MATCH_PASSWORD = 4
|
||||||
|
|
||||||
|
|
||||||
|
class CouldNotMatchUsername(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class CouldNotMatchPassword(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def qute_command(command):
|
||||||
|
with open(os.environ['QUTE_FIFO'], 'w') as fifo:
|
||||||
|
fifo.write(command + '\n')
|
||||||
|
fifo.flush()
|
||||||
|
|
||||||
|
# Encode candidate string parts as Internationalized Domain Name, doing
|
||||||
|
# Unicode normalization before. This allows to properly match (non-ASCII)
|
||||||
|
# pass entries with the corresponding domain names.
|
||||||
|
def idna_encode(name):
|
||||||
|
# Do Unicode normalization first, we use form NFKC because:
|
||||||
|
# 1. Use the compatibility normalization because these sequences have "the same meaning in some contexts"
|
||||||
|
# 2. idna.encode() below requires the Unicode strings to be in normalization form C
|
||||||
|
# See https://en.wikipedia.org/wiki/Unicode_equivalence#Normal_forms
|
||||||
|
unicode_normalized = unicodedata.normalize("NFKC", name)
|
||||||
|
# Empty strings can not be encoded, they appear for example as empty
|
||||||
|
# parts in split_path. If something like this happens, we just fall back
|
||||||
|
# to the unicode representation (which may already be ASCII then).
|
||||||
|
try:
|
||||||
|
idna_encoded = idna.encode(unicode_normalized)
|
||||||
|
except idna.IDNAError:
|
||||||
|
idna_encoded = unicode_normalized
|
||||||
|
return idna_encoded
|
||||||
|
|
||||||
|
def find_pass_candidates(domain, unfiltered=False):
|
||||||
|
candidates = []
|
||||||
|
|
||||||
|
if arguments.mode == "gopass":
|
||||||
|
gopass_args = ["gopass", "list", "--flat"]
|
||||||
|
if arguments.prefix:
|
||||||
|
gopass_args.append(arguments.prefix)
|
||||||
|
all_passwords = subprocess.run(gopass_args, stdout=subprocess.PIPE).stdout.decode("UTF-8").splitlines()
|
||||||
|
|
||||||
|
for password in all_passwords:
|
||||||
|
if unfiltered or domain in password:
|
||||||
|
candidates.append(password)
|
||||||
|
else:
|
||||||
|
idna_domain = idna_encode(domain)
|
||||||
|
for path, directories, file_names in os.walk(arguments.password_store, followlinks=True):
|
||||||
|
secrets = fnmatch.filter(file_names, '*.gpg')
|
||||||
|
if not secrets:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Strip password store path prefix to get the relative pass path
|
||||||
|
pass_path = path[len(arguments.password_store):]
|
||||||
|
split_path = pass_path.split(os.path.sep)
|
||||||
|
idna_split_path = [idna_encode(part) for part in split_path]
|
||||||
|
for secret in secrets:
|
||||||
|
secret_base = os.path.splitext(secret)[0]
|
||||||
|
idna_secret_base = idna_encode(secret_base)
|
||||||
|
if not unfiltered and idna_domain not in (idna_split_path + [idna_secret_base]):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Append the unencoded Unicode path/name since this is how pass uses them
|
||||||
|
candidates.append(os.path.join(pass_path, secret_base))
|
||||||
|
return candidates
|
||||||
|
|
||||||
|
|
||||||
|
def _run_pass(pass_arguments):
|
||||||
|
# The executable is conveniently named after it's mode [pass|gopass].
|
||||||
|
pass_command = [arguments.mode]
|
||||||
|
env = os.environ.copy()
|
||||||
|
env['PASSWORD_STORE_DIR'] = arguments.password_store
|
||||||
|
process = subprocess.run(pass_command + pass_arguments, env=env, stdout=subprocess.PIPE)
|
||||||
|
return process.stdout.decode(arguments.io_encoding).strip()
|
||||||
|
|
||||||
|
|
||||||
|
def pass_(path):
|
||||||
|
return _run_pass(['show', path])
|
||||||
|
|
||||||
|
|
||||||
|
def pass_otp(path):
|
||||||
|
if arguments.mode == "gopass":
|
||||||
|
return _run_pass(['otp', '-o', path])
|
||||||
|
return _run_pass(['otp', path])
|
||||||
|
|
||||||
|
|
||||||
|
def dmenu(items, invocation):
|
||||||
|
command = shlex.split(invocation)
|
||||||
|
process = subprocess.run(command, input='\n'.join(items).encode(arguments.io_encoding), stdout=subprocess.PIPE)
|
||||||
|
return process.stdout.decode(arguments.io_encoding).strip()
|
||||||
|
|
||||||
|
|
||||||
|
def fake_key_raw(text):
|
||||||
|
for character in text:
|
||||||
|
# Escape all characters by default, space requires special handling
|
||||||
|
sequence = '" "' if character == ' ' else r'\{}'.format(character)
|
||||||
|
qute_command('fake-key {}'.format(sequence))
|
||||||
|
|
||||||
|
|
||||||
|
def extract_password(secret, pattern):
|
||||||
|
match = re.match(pattern, secret)
|
||||||
|
if not match:
|
||||||
|
raise CouldNotMatchPassword("Pattern did not match target")
|
||||||
|
try:
|
||||||
|
return match.group(1)
|
||||||
|
except IndexError:
|
||||||
|
raise CouldNotMatchPassword("Pattern did not contain capture group, please use capture group. Example: (.*)")
|
||||||
|
|
||||||
|
|
||||||
|
def extract_username(target, pattern):
|
||||||
|
match = re.search(pattern, target, re.MULTILINE)
|
||||||
|
if not match:
|
||||||
|
raise CouldNotMatchUsername("Pattern did not match target")
|
||||||
|
try:
|
||||||
|
return match.group(1)
|
||||||
|
except IndexError:
|
||||||
|
raise CouldNotMatchUsername("Pattern did not contain capture group, please use capture group. Example: (.*)")
|
||||||
|
|
||||||
|
|
||||||
|
def main(arguments):
|
||||||
|
if not arguments.url:
|
||||||
|
argument_parser.print_help()
|
||||||
|
return ExitCodes.FAILURE
|
||||||
|
|
||||||
|
extractor = tldextract.TLDExtract(extra_suffixes=arguments.extra_url_suffixes.split(','))
|
||||||
|
extract_result = extractor(arguments.url)
|
||||||
|
|
||||||
|
# Try to find candidates using targets in the following order: fully-qualified domain name (includes subdomains),
|
||||||
|
# the registered domain name, the IPv4 address if that's what the URL represents and finally the private domain
|
||||||
|
# (if a non-public suffix was used), and the URL netloc.
|
||||||
|
candidates = set()
|
||||||
|
attempted_targets = []
|
||||||
|
|
||||||
|
private_domain = ''
|
||||||
|
if not extract_result.suffix:
|
||||||
|
private_domain = ('.'.join((extract_result.subdomain, extract_result.domain))
|
||||||
|
if extract_result.subdomain else extract_result.domain)
|
||||||
|
|
||||||
|
netloc = urlparse(arguments.url).netloc
|
||||||
|
|
||||||
|
for target in filter(None, [extract_result.fqdn, extract_result.registered_domain, extract_result.ipv4, private_domain, netloc]):
|
||||||
|
attempted_targets.append(target)
|
||||||
|
target_candidates = find_pass_candidates(target, unfiltered=arguments.unfiltered)
|
||||||
|
if not target_candidates:
|
||||||
|
continue
|
||||||
|
|
||||||
|
candidates.update(target_candidates)
|
||||||
|
if not arguments.merge_candidates:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
if not candidates:
|
||||||
|
stderr('No pass candidates for URL {!r} found! (I tried {!r})'.format(arguments.url, attempted_targets))
|
||||||
|
return ExitCodes.NO_PASS_CANDIDATES
|
||||||
|
|
||||||
|
if len(candidates) == 1 and not arguments.always_show_selection:
|
||||||
|
selection = candidates.pop()
|
||||||
|
else:
|
||||||
|
selection = dmenu(sorted(candidates), arguments.dmenu_invocation)
|
||||||
|
|
||||||
|
# Nothing was selected, simply return
|
||||||
|
if not selection:
|
||||||
|
return ExitCodes.SUCCESS
|
||||||
|
|
||||||
|
# If username-target is path and user asked for username-only, we don't need to run pass.
|
||||||
|
# Or if using otp-only, it will run pass on its own.
|
||||||
|
secret = None
|
||||||
|
if not (arguments.username_target == 'path' and arguments.username_only) and not arguments.otp_only:
|
||||||
|
secret = pass_(selection)
|
||||||
|
username_target = selection if arguments.username_target == 'path' else secret
|
||||||
|
try:
|
||||||
|
if arguments.username_only:
|
||||||
|
fake_key_raw(extract_username(username_target, arguments.username_pattern))
|
||||||
|
elif arguments.password_only:
|
||||||
|
fake_key_raw(extract_password(secret, arguments.password_pattern))
|
||||||
|
elif arguments.otp_only:
|
||||||
|
otp = pass_otp(selection)
|
||||||
|
fake_key_raw(otp)
|
||||||
|
else:
|
||||||
|
# Enter username and password using fake-key and <Tab> (which seems to work almost universally), then switch
|
||||||
|
# back into insert-mode, so the form can be directly submitted by hitting enter afterwards
|
||||||
|
fake_key_raw(extract_username(username_target, arguments.username_pattern))
|
||||||
|
qute_command('fake-key <Tab>')
|
||||||
|
fake_key_raw(extract_password(secret, arguments.password_pattern))
|
||||||
|
except CouldNotMatchPassword as e:
|
||||||
|
stderr('Failed to match password, target: secret, error: {}'.format(e))
|
||||||
|
return ExitCodes.COULD_NOT_MATCH_PASSWORD
|
||||||
|
except CouldNotMatchUsername as e:
|
||||||
|
stderr('Failed to match username, target: {}, error: {}'.format(arguments.username_target, e))
|
||||||
|
return ExitCodes.COULD_NOT_MATCH_USERNAME
|
||||||
|
|
||||||
|
if arguments.insert_mode:
|
||||||
|
qute_command('mode-enter insert')
|
||||||
|
|
||||||
|
return ExitCodes.SUCCESS
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
arguments = argument_parser.parse_args()
|
||||||
|
sys.exit(main(arguments))
|
||||||
900
home/.local/usr/bin/rofi-pass
Executable file
900
home/.local/usr/bin/rofi-pass
Executable file
@@ -0,0 +1,900 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# rofi-pass
|
||||||
|
# (c) 2015 Rasmus Steinke <rasi@xssn.at>
|
||||||
|
basecommand="$0"
|
||||||
|
|
||||||
|
# set default settings
|
||||||
|
_rofi () {
|
||||||
|
rofi -no-auto-select -i "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
_pwgen () {
|
||||||
|
pwgen -y "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
_image_viewer () {
|
||||||
|
feh -
|
||||||
|
}
|
||||||
|
|
||||||
|
_clip_in_primary() {
|
||||||
|
xclip
|
||||||
|
}
|
||||||
|
|
||||||
|
_clip_in_clipboard() {
|
||||||
|
xclip -selection clipboard
|
||||||
|
}
|
||||||
|
|
||||||
|
_clip_out_primary() {
|
||||||
|
xclip -o
|
||||||
|
}
|
||||||
|
|
||||||
|
_clip_out_clipboard() {
|
||||||
|
xclip --selection clipboard -o
|
||||||
|
}
|
||||||
|
|
||||||
|
export PASSWORD_STORE_DIR="${HOME}/.passwords/"
|
||||||
|
config_dir=${XDG_CONFIG_HOME:-$HOME/.config}
|
||||||
|
cache_dir=${XDG_CACHE_HOME:-$HOME/.cache}
|
||||||
|
|
||||||
|
# We expect to find these fields in pass(1)'s output
|
||||||
|
URL_field='url'
|
||||||
|
USERNAME_field='user'
|
||||||
|
AUTOTYPE_field='autotype'
|
||||||
|
OTPmethod_field='otp_method'
|
||||||
|
|
||||||
|
default_autotype="user :tab pass"
|
||||||
|
delay=2
|
||||||
|
wait=0.2
|
||||||
|
xdotool_delay=12
|
||||||
|
default_do='menu' # menu, copyPass, typeUser, typePass, copyUser, copyUrl, viewEntry, typeMenu, actionMenu, copyMenu, openUrl
|
||||||
|
auto_enter='false'
|
||||||
|
notify='false'
|
||||||
|
help_color=""
|
||||||
|
clip=primary
|
||||||
|
clip_clear=45
|
||||||
|
default_user="${ROFI_PASS_DEFAULT_USER-$(whoami)}"
|
||||||
|
default_user2=john_doe
|
||||||
|
password_length=12
|
||||||
|
fix_layout=false
|
||||||
|
|
||||||
|
# default shortcuts
|
||||||
|
autotype="Alt+1"
|
||||||
|
type_user="Alt+2"
|
||||||
|
type_pass="Alt+3"
|
||||||
|
open_url="Alt+4"
|
||||||
|
copy_name="Alt+u"
|
||||||
|
copy_url="Alt+l"
|
||||||
|
copy_pass="Alt+p"
|
||||||
|
show="Alt+o"
|
||||||
|
copy_menu="Alt+c"
|
||||||
|
action_menu="Alt+a"
|
||||||
|
type_menu="Alt+t"
|
||||||
|
help="Alt+h"
|
||||||
|
switch="Alt+x"
|
||||||
|
insert_pass="Alt+n"
|
||||||
|
qrcode="Alt+q"
|
||||||
|
previous_root="Shift+Left"
|
||||||
|
next_root="Shift+Right"
|
||||||
|
|
||||||
|
# Safe permissions
|
||||||
|
umask 077
|
||||||
|
|
||||||
|
has_qrencode() {
|
||||||
|
command -v qrencode >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
listgpg () {
|
||||||
|
mapfile -d '' pw_list < <(find -L . -name '*.gpg' -print0)
|
||||||
|
pw_list=("${pw_list[@]#./}")
|
||||||
|
printf '%s\n' "${pw_list[@]}" | sort -n
|
||||||
|
}
|
||||||
|
|
||||||
|
# get all password files and output as newline-delimited text
|
||||||
|
list_passwords() {
|
||||||
|
cd "${root}" || exit
|
||||||
|
mapfile -t pw_list < <(listgpg)
|
||||||
|
printf '%s\n' "${pw_list[@]%.gpg}" | sort -n
|
||||||
|
}
|
||||||
|
|
||||||
|
doClip () {
|
||||||
|
case "$clip" in
|
||||||
|
"primary") _clip_in_primary ;;
|
||||||
|
"clipboard") _clip_in_clipboard ;;
|
||||||
|
"both") _clip_in_primary; _clip_out_primary | _clip_in_clipboard;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
checkIfPass () {
|
||||||
|
printf '%s\n' "${root}: $selected_password" >| "$cache_dir/rofi-pass/last_used"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
autopass () {
|
||||||
|
x_repeat_enabled=$(xset q | awk '/auto repeat:/ {print $3}')
|
||||||
|
xset r off
|
||||||
|
|
||||||
|
rm -f "$cache_dir/rofi-pass/last_used"
|
||||||
|
printf '%s\n' "${root}: $selected_password" > "$cache_dir/rofi-pass/last_used"
|
||||||
|
for word in ${stuff["$AUTOTYPE_field"]}; do
|
||||||
|
case "$word" in
|
||||||
|
":tab") xdotool key Tab;;
|
||||||
|
":space") xdotool key space;;
|
||||||
|
":delay") sleep "${delay}";;
|
||||||
|
":enter") xdotool key Return;;
|
||||||
|
":otp") printf '%s' "$(generateOTP)" | xdotool type --delay ${xdotool_delay} --clearmodifiers --file -;;
|
||||||
|
"pass") printf '%s' "${password}" | xdotool type --delay ${xdotool_delay} --clearmodifiers --file -;;
|
||||||
|
"path") printf '%s' "${selected_password}" | rev | cut -d'/' -f1 | rev | xdotool type --clearmodifiers --file -;;
|
||||||
|
*) printf '%s' "${stuff[${word}]}" | xdotool type --delay ${xdotool_delay} --clearmodifiers --file -;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ ${auto_enter} == "true" ]]; then
|
||||||
|
xdotool key Return
|
||||||
|
fi
|
||||||
|
|
||||||
|
xset r "$x_repeat_enabled"
|
||||||
|
unset x_repeat_enabled
|
||||||
|
clearUp
|
||||||
|
}
|
||||||
|
|
||||||
|
generateQrCode() {
|
||||||
|
has_qrencode
|
||||||
|
|
||||||
|
if [[ $? -eq "1" ]]; then
|
||||||
|
printf '%s\n' "qrencode not found" | _rofi -dmenu
|
||||||
|
exit_code=$?
|
||||||
|
if [[ $exit_code -eq "1" ]]; then
|
||||||
|
exit
|
||||||
|
else
|
||||||
|
"${basecommand}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
checkIfPass
|
||||||
|
pass "$selected_password" | head -n 1 | qrencode -d 300 -v 8 -l H -o - | _image_viewer
|
||||||
|
if [[ $? -eq "1" ]]; then
|
||||||
|
printf '%s\n' "" | _rofi -dmenu -mesg "Image viewer not defined or cannot read from pipe"
|
||||||
|
exit_value=$?
|
||||||
|
if [[ $exit_value -eq "1" ]]; then
|
||||||
|
exit
|
||||||
|
else
|
||||||
|
"${basecommand}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
clearUp
|
||||||
|
}
|
||||||
|
|
||||||
|
openURL () {
|
||||||
|
checkIfPass
|
||||||
|
$BROWSER "$(PASSWORD_STORE_DIR="${root}" pass "$selected_password" | grep "${URL_field}: " | gawk '{sub(/:/,"")}{print $2}1' | head -1)"; exit;
|
||||||
|
clearUp
|
||||||
|
}
|
||||||
|
|
||||||
|
typeUser () {
|
||||||
|
checkIfPass
|
||||||
|
|
||||||
|
x_repeat_enabled=$(xset q | awk '/auto repeat:/ {print $3}')
|
||||||
|
xset r off
|
||||||
|
|
||||||
|
printf '%s' "${stuff[${USERNAME_field}]}" | xdotool type --delay ${xdotool_delay} --clearmodifiers --file -
|
||||||
|
|
||||||
|
xset r "$x_repeat_enabled"
|
||||||
|
unset x_repeat_enabled
|
||||||
|
|
||||||
|
clearUp
|
||||||
|
}
|
||||||
|
|
||||||
|
typePass () {
|
||||||
|
checkIfPass
|
||||||
|
|
||||||
|
x_repeat_enabled=$(xset q | awk '/auto repeat:/ {print $3}')
|
||||||
|
xset r off
|
||||||
|
|
||||||
|
printf '%s' "${password}" | xdotool type --delay ${xdotool_delay} --clearmodifiers --file -
|
||||||
|
|
||||||
|
if [[ $notify == "true" ]]; then
|
||||||
|
if [[ "${stuff[notify]}" == "false" ]]; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
notify-send "rofi-pass" "finished typing password";
|
||||||
|
fi
|
||||||
|
elif [[ $notify == "false" ]]; then
|
||||||
|
if [[ "${stuff[notify]}" == "true" ]]; then
|
||||||
|
notify-send "rofi-pass" "finished typing password";
|
||||||
|
else
|
||||||
|
:
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
xset r "$x_repeat_enabled"
|
||||||
|
unset x_repeat_enabled
|
||||||
|
clearUp
|
||||||
|
}
|
||||||
|
|
||||||
|
typeField () {
|
||||||
|
checkIfPass
|
||||||
|
local to_type
|
||||||
|
|
||||||
|
x_repeat_enabled=$(xset q | awk '/auto repeat:/ {print $3}')
|
||||||
|
xset r off
|
||||||
|
|
||||||
|
case $typefield in
|
||||||
|
"OTP") to_type="$(generateOTP)" ;;
|
||||||
|
*) to_type="${stuff[${typefield}]}" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
printf '%s' "$to_type" | xdotool type --delay ${xdotool_delay} --clearmodifiers --file -
|
||||||
|
|
||||||
|
xset r "$x_repeat_enabled"
|
||||||
|
unset x_repeat_enabled
|
||||||
|
unset to_type
|
||||||
|
|
||||||
|
clearUp
|
||||||
|
}
|
||||||
|
|
||||||
|
generateOTP () {
|
||||||
|
checkIfPass
|
||||||
|
|
||||||
|
# First, we check if there is a non-conventional OTP command in the pass file
|
||||||
|
if PASSWORD_STORE_DIR="${root}" pass "$selected_password" | grep -q "${OTPmethod_field}: "; then
|
||||||
|
# We execute the commands after otp_method: AS-IS
|
||||||
|
bash -c "$(PASSWORD_STORE_DIR="${root}" pass "$selected_password" | grep "${OTPmethod_field}: " | cut -d' ' -f2-)"
|
||||||
|
else
|
||||||
|
# If there is no method defined, fallback to pass-otp
|
||||||
|
PASSWORD_STORE_DIR="${root}" pass otp "$selected_password"
|
||||||
|
fi
|
||||||
|
|
||||||
|
clearUp
|
||||||
|
}
|
||||||
|
|
||||||
|
copyUser () {
|
||||||
|
checkIfPass
|
||||||
|
printf '%s' "${stuff[${USERNAME_field}]}" | doClip
|
||||||
|
clearUp
|
||||||
|
}
|
||||||
|
|
||||||
|
copyField () {
|
||||||
|
checkIfPass
|
||||||
|
printf '%s' "${stuff[${copyfield}]}" | doClip
|
||||||
|
clearUp
|
||||||
|
}
|
||||||
|
|
||||||
|
copyURL () {
|
||||||
|
checkIfPass
|
||||||
|
printf '%s' "${stuff[${URL_field}]}" | doClip
|
||||||
|
clearUp
|
||||||
|
}
|
||||||
|
|
||||||
|
copyPass () {
|
||||||
|
checkIfPass
|
||||||
|
printf '%s' "$password" | doClip
|
||||||
|
if [[ $notify == "true" ]]; then
|
||||||
|
notify-send "rofi-pass" "Copied Password\\nClearing in $clip_clear seconds"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $notify == "true" ]]; then
|
||||||
|
(sleep $clip_clear; printf '%s' "" | _clip_in_primary; printf '%s' "" | _clip_in_clipboard | notify-send "rofi-pass" "Clipboard cleared") &
|
||||||
|
elif [[ $notify == "false" ]]; then
|
||||||
|
(sleep $clip_clear; printf '%s' "" | _clip_in_primary; printf '%s' "" | _clip_in_clipboard) &
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
viewEntry () {
|
||||||
|
checkIfPass
|
||||||
|
showEntry "${selected_password}"
|
||||||
|
}
|
||||||
|
|
||||||
|
generatePass () {
|
||||||
|
askmenu_content=(
|
||||||
|
"Yes"
|
||||||
|
"No"
|
||||||
|
)
|
||||||
|
|
||||||
|
askGenMenu=$(printf '%s\n' "${askmenu_content[@]}" | _rofi -dmenu -p "Generate new Password for ${selected_password}? > ")
|
||||||
|
askgen_exit=$?
|
||||||
|
|
||||||
|
if [[ $askgen_exit -eq 1 ]]; then
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
if [[ $askGenMenu == "Yes" ]]; then
|
||||||
|
true
|
||||||
|
elif [[ $askGenMenu == "No" ]]; then
|
||||||
|
actionMenu
|
||||||
|
fi
|
||||||
|
|
||||||
|
checkIfPass
|
||||||
|
|
||||||
|
symbols_content=(
|
||||||
|
"0 Cancel"
|
||||||
|
"1 Yes"
|
||||||
|
"2 No"
|
||||||
|
)
|
||||||
|
|
||||||
|
symbols=$(printf '%s\n' "${symbols_content[@]}" | _rofi -dmenu -p "Use Symbols? > ")
|
||||||
|
symbols_val=$?
|
||||||
|
|
||||||
|
if [[ $symbols_val -eq 1 ]]; then
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
if [[ $symbols == "0 Cancel" ]]; then
|
||||||
|
mainMenu;
|
||||||
|
elif [[ $symbols == "1 Yes" ]]; then
|
||||||
|
symbols="";
|
||||||
|
elif [[ $symbols == "2 No" ]]; then
|
||||||
|
symbols="-n";
|
||||||
|
fi
|
||||||
|
|
||||||
|
HELP="<span color='$help_color'>Enter Number or hit Enter to use default length</span>"
|
||||||
|
length=$(printf '%s' "" | _rofi -dmenu -mesg "${HELP}" -p "Password length? (Default: ${password_length}) > ")
|
||||||
|
length_exit=$?
|
||||||
|
|
||||||
|
if [[ $length_exit -eq 1 ]]; then
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
if [[ $length == "" ]]; then
|
||||||
|
PASSWORD_STORE_DIR="${root}" pass generate ${symbols} -i "$selected_password" "${password_length}" > /dev/null;
|
||||||
|
else
|
||||||
|
PASSWORD_STORE_DIR="${root}" pass generate ${symbols} -i "$selected_password" "${length}" > /dev/null;
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# main Menu
|
||||||
|
mainMenu () {
|
||||||
|
if [[ $1 == "--bmarks" ]]; then
|
||||||
|
selected_password="$(list_passwords 2>/dev/null \
|
||||||
|
| _rofi -mesg "Bookmarks Mode. ${switch} to switch" \
|
||||||
|
-dmenu \
|
||||||
|
-kb-custom-10 "${switch}" \
|
||||||
|
-select "$entry" \
|
||||||
|
-p "rofi-pass > ")"
|
||||||
|
|
||||||
|
rofi_exit=$?
|
||||||
|
|
||||||
|
if [[ $rofi_exit -eq 1 ]]; then
|
||||||
|
exit
|
||||||
|
elif [[ $rofi_exit -eq 19 ]]; then
|
||||||
|
${basecommand}
|
||||||
|
elif [[ $rofi_exit -eq 0 ]]; then
|
||||||
|
openURL
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
unset selected_password
|
||||||
|
|
||||||
|
args=( -dmenu
|
||||||
|
-kb-custom-1 "${autotype}"
|
||||||
|
-kb-custom-2 "${type_user}"
|
||||||
|
-kb-custom-3 "${type_pass}"
|
||||||
|
-kb-custom-4 "${open_url}"
|
||||||
|
-kb-custom-5 "${copy_name}"
|
||||||
|
-kb-custom-6 "${copy_pass}"
|
||||||
|
-kb-custom-7 "${show}"
|
||||||
|
-kb-custom-8 "${copy_url}"
|
||||||
|
-kb-custom-9 "${type_menu}"
|
||||||
|
-kb-custom-10 "${previous_root}"
|
||||||
|
-kb-custom-11 "${next_root}"
|
||||||
|
-kb-custom-14 "${action_menu}"
|
||||||
|
-kb-custom-15 "${copy_menu}"
|
||||||
|
-kb-custom-16 "${help}"
|
||||||
|
-kb-custom-17 "${switch}"
|
||||||
|
-kb-custom-18 "${insert_pass}"
|
||||||
|
-kb-custom-19 "${qrcode}"
|
||||||
|
)
|
||||||
|
args+=( -kb-mode-previous "" # These keyboard shortcut options are needed, because
|
||||||
|
-kb-mode-next "" # Shift+<Left|Right> are otherwise taken by rofi.
|
||||||
|
-select "$entry"
|
||||||
|
-p "> " )
|
||||||
|
|
||||||
|
if [[ ${#roots[@]} -gt "1" || $custom_root == "true" ]]; then
|
||||||
|
args+=(-mesg "PW Store: ${root}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
selected_password="$(list_passwords 2>/dev/null | _rofi "${args[@]}")"
|
||||||
|
|
||||||
|
rofi_exit=$?
|
||||||
|
if [[ $rofi_exit -eq 1 ]]; then
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Actions based on exit code, which do not need the entry.
|
||||||
|
# The exit code for -kb-custom-X is X+9.
|
||||||
|
case "${rofi_exit}" in
|
||||||
|
19) roots_index=$(( (roots_index-1+roots_length) % roots_length)); root=${roots[$roots_index]}; mainMenu; return;;
|
||||||
|
20) roots_index=$(( (roots_index+1) % roots_length)); root=${roots[$roots_index]}; mainMenu; return;;
|
||||||
|
25) helpMenu; return;;
|
||||||
|
26) ${basecommand} --bmarks; return;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
mapfile -t password_temp < <(PASSWORD_STORE_DIR="${root}" pass show "$selected_password")
|
||||||
|
password=${password_temp[0]}
|
||||||
|
|
||||||
|
if [[ ${password} == "#FILE="* ]]; then
|
||||||
|
pass_file="${password#*=}"
|
||||||
|
mapfile -t password_temp2 < <(PASSWORD_STORE_DIR="${root}" pass show "${pass_file}")
|
||||||
|
password=${password_temp2[0]}
|
||||||
|
fi
|
||||||
|
|
||||||
|
fields=$(printf '%s\n' "${password_temp[@]:1}" | awk '$1 ~ /:$/ || /otpauth:\/\// {$1=$1;print}')
|
||||||
|
declare -A stuff
|
||||||
|
stuff["pass"]=${password}
|
||||||
|
|
||||||
|
if [[ -n $fields ]]; then
|
||||||
|
while read -r LINE; do
|
||||||
|
unset _id _val
|
||||||
|
case "$LINE" in
|
||||||
|
"otpauth://"*|"${OTPmethod_field}"*)
|
||||||
|
_id="OTP"
|
||||||
|
_val=""
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
_id="${LINE%%: *}"
|
||||||
|
_val="${LINE#* }"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [[ -n "$_id" ]]; then
|
||||||
|
stuff["${_id}"]=${_val}
|
||||||
|
fi
|
||||||
|
done < <(printf '%s\n' "${fields}")
|
||||||
|
|
||||||
|
if test "${stuff['autotype']+autotype}"; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
stuff["autotype"]="${USERNAME_field} :tab pass"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${stuff["${AUTOTYPE_field}"]}" ]]; then
|
||||||
|
if [[ -n $default_autotype ]]; then
|
||||||
|
stuff["${AUTOTYPE_field}"]="${default_autotype}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [[ -z "${stuff["${USERNAME_field}"]}" ]]; then
|
||||||
|
if [[ -n $default_user ]]; then
|
||||||
|
if [[ "$default_user" == ":filename" ]]; then
|
||||||
|
stuff["${USERNAME_field}"]="$(basename "$selected_password")"
|
||||||
|
else
|
||||||
|
stuff["${USERNAME_field}"]="${default_user}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
pass_content="$(for key in "${!stuff[@]}"; do printf '%s\n' "${key}: ${stuff[$key]}"; done)"
|
||||||
|
|
||||||
|
# actions based on keypresses
|
||||||
|
# The exit code for -kb-custom-X is X+9.
|
||||||
|
case "${rofi_exit}" in
|
||||||
|
0) typeMenu;;
|
||||||
|
10) sleep $wait; autopass;;
|
||||||
|
11) sleep $wait; typeUser;;
|
||||||
|
12) sleep $wait; typePass;;
|
||||||
|
13) openURL;;
|
||||||
|
14) copyUser;;
|
||||||
|
15) copyPass;;
|
||||||
|
16) viewEntry;;
|
||||||
|
17) copyURL;;
|
||||||
|
18) default_do="menu" typeMenu;;
|
||||||
|
23) actionMenu;;
|
||||||
|
24) copyMenu;;
|
||||||
|
27) insertPass;;
|
||||||
|
28) generateQrCode;;
|
||||||
|
esac
|
||||||
|
clearUp
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
clearUp () {
|
||||||
|
password=''
|
||||||
|
selected_password=''
|
||||||
|
unset stuff
|
||||||
|
unset password
|
||||||
|
unset selected_password
|
||||||
|
unset password_temp
|
||||||
|
unset stuff
|
||||||
|
}
|
||||||
|
|
||||||
|
helpMenu () {
|
||||||
|
_rofi -dmenu -mesg "Hint: All hotkeys are configurable in config file" -p "Help > " <<- EOM
|
||||||
|
${autotype}: Autotype
|
||||||
|
${type_user}: Type Username
|
||||||
|
${type_pass}: Type Password
|
||||||
|
${qrcode}: Generate and display qrcode
|
||||||
|
---
|
||||||
|
${copy_name}: Copy Username
|
||||||
|
${copy_pass}: Copy Password
|
||||||
|
${copy_url}: Copy URL
|
||||||
|
${open_url}: Open URL
|
||||||
|
${copy_menu}: Copy Custom Field
|
||||||
|
---
|
||||||
|
${action_menu}: Edit, Move, Delete, Re-generate Submenu
|
||||||
|
${show}: Show Password File
|
||||||
|
${insert_pass}: Insert new Pass Entry
|
||||||
|
${switch}: Switch Pass/Bookmark Mode
|
||||||
|
---
|
||||||
|
${previous_root}: Switch to previous password store (--root)
|
||||||
|
${next_root}: Switch to next password store (--root)
|
||||||
|
EOM
|
||||||
|
help_val=$?
|
||||||
|
|
||||||
|
if [[ $help_val -eq 1 ]]; then
|
||||||
|
exit;
|
||||||
|
else
|
||||||
|
unset helptext; mainMenu;
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typeMenu () {
|
||||||
|
if [[ -n $default_do ]]; then
|
||||||
|
if [[ $default_do == "menu" ]]; then
|
||||||
|
checkIfPass
|
||||||
|
local -a keys=("${!stuff[@]}")
|
||||||
|
keys=("${keys[@]/$AUTOTYPE_field}")
|
||||||
|
typefield=$({ printf '%s' "${AUTOTYPE_field}" ; printf '%s\n' "${keys[@]}" | sort; } | _rofi -dmenu -p "Choose Field to type > ")
|
||||||
|
typefield_exit=$?
|
||||||
|
if [[ $typefield_exit -eq 1 ]]; then
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
case "$typefield" in
|
||||||
|
'') exit;;
|
||||||
|
'pass') sleep $wait; typePass;;
|
||||||
|
"${AUTOTYPE_field}") sleep $wait; autopass;;
|
||||||
|
*) sleep $wait; typeField
|
||||||
|
esac
|
||||||
|
clearUp
|
||||||
|
elif [[ $default_do == "${AUTOTYPE_field}" ]]; then
|
||||||
|
sleep $wait; autopass
|
||||||
|
else
|
||||||
|
${default_do}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
copyMenu () {
|
||||||
|
checkIfPass
|
||||||
|
copyfield=$(printf '%s\n' "${!stuff[@]}" | sort | _rofi -dmenu -p "Choose Field to copy > ")
|
||||||
|
val=$?
|
||||||
|
if [[ $val -eq 1 ]]; then
|
||||||
|
exit;
|
||||||
|
fi
|
||||||
|
if [[ $copyfield == "pass" ]]; then
|
||||||
|
copyPass;
|
||||||
|
else
|
||||||
|
copyField
|
||||||
|
fi
|
||||||
|
clearUp
|
||||||
|
}
|
||||||
|
|
||||||
|
actionMenu () {
|
||||||
|
checkIfPass
|
||||||
|
action_content=("< Return"
|
||||||
|
"---"
|
||||||
|
"1 Move Password File"
|
||||||
|
"2 Copy Password File"
|
||||||
|
"3 Delete Password File"
|
||||||
|
"4 Edit Password File"
|
||||||
|
"5 Generate New Password"
|
||||||
|
)
|
||||||
|
|
||||||
|
action=$(printf '%s\n' "${action_content[@]}" | _rofi -dmenu -p "Choose Action > ")
|
||||||
|
if [[ ${action} == "1 Move Password File" ]]; then
|
||||||
|
manageEntry move;
|
||||||
|
elif [[ ${action} == "3 Delete Password File" ]]; then
|
||||||
|
manageEntry delete;
|
||||||
|
elif [[ ${action} == "2 Copy Password File" ]]; then
|
||||||
|
manageEntry copy;
|
||||||
|
elif [[ ${action} == "4 Edit Password File" ]]; then
|
||||||
|
manageEntry edit;
|
||||||
|
elif [[ ${action} == "5 Generate New Password" ]]; then
|
||||||
|
generatePass;
|
||||||
|
elif [[ ${action} == "< Return" ]]; then
|
||||||
|
mainMenu;
|
||||||
|
elif [[ ${action} == "" ]]; then
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
showEntry () {
|
||||||
|
if [[ -z $pass_content ]]; then
|
||||||
|
pass_temp=$(PASSWORD_STORE_DIR="${root}" pass show "$selected_password")
|
||||||
|
password="${pass_temp%%$'\n'*}"
|
||||||
|
pass_key_value=$(printf '%s\n' "${pass_temp}" | tail -n+2 | grep ': ')
|
||||||
|
declare -A stuff
|
||||||
|
|
||||||
|
while read -r LINE; do
|
||||||
|
_id="${LINE%%: *}"
|
||||||
|
_val="${LINE#* }"
|
||||||
|
stuff["${_id}"]=${_val}
|
||||||
|
done < <(printf '%s\n' "${pass_key_value}")
|
||||||
|
|
||||||
|
stuff["pass"]=${password}
|
||||||
|
|
||||||
|
if test "${stuff['autotype']+autotype}"; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
stuff["autotype"]="${USERNAME_field} :tab pass"
|
||||||
|
fi
|
||||||
|
|
||||||
|
pass_content="$(for key in "${!stuff[@]}"; do printf '%s\n' "${key}: ${stuff[$key]}"; done)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
bla_content=("< Return"
|
||||||
|
"${pass_content}"
|
||||||
|
)
|
||||||
|
|
||||||
|
bla=$(printf '%s\n' "${bla_content[@]}" | _rofi -dmenu -mesg "Enter: Copy entry to clipboard" -p "> ")
|
||||||
|
rofi_exit=$?
|
||||||
|
|
||||||
|
word=$(printf '%s' "$bla" | gawk -F': ' '{print $1}')
|
||||||
|
|
||||||
|
if [[ ${rofi_exit} -eq 1 ]]; then
|
||||||
|
exit
|
||||||
|
elif [[ ${rofi_exit} -eq 0 ]]; then
|
||||||
|
if [[ ${bla} == "< Return" ]]; then
|
||||||
|
mainMenu
|
||||||
|
else
|
||||||
|
if [[ -z $(printf '%s' "${stuff[${word}]}") ]]; then
|
||||||
|
printf '%s' "$word" | doClip
|
||||||
|
else
|
||||||
|
printf '%s' "${stuff[${word}]}" | doClip
|
||||||
|
fi
|
||||||
|
if [[ $notify == "true" ]]; then
|
||||||
|
notify-send "rofi-pass" "Copied Password\\nClearing in $clip_clear seconds"
|
||||||
|
fi
|
||||||
|
if [[ $notify == "true" ]]; then
|
||||||
|
(sleep $clip_clear; printf '%s' "" | _clip_in_primary; printf '%s' "" | _clip_in_clipboard | notify-send "rofi-pass" "Clipboard cleared") &
|
||||||
|
elif [[ $notify == "false" ]]; then
|
||||||
|
(sleep $clip_clear; printf '%s' "" | _clip_in_primary; printf '%s' "" | _clip_in_clipboard) &
|
||||||
|
fi
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
exit
|
||||||
|
unset stuff
|
||||||
|
unset password
|
||||||
|
unset selected_password
|
||||||
|
unset password_temp
|
||||||
|
unset stuff
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
manageEntry () {
|
||||||
|
if [[ "$1" == "edit" ]]; then
|
||||||
|
EDITOR=$EDITOR PASSWORD_STORE_DIR="${root}" pass edit "${selected_password}"
|
||||||
|
mainMenu
|
||||||
|
elif [[ $1 == "move" ]]; then
|
||||||
|
cd "${root}" || exit
|
||||||
|
group_array=(*/)
|
||||||
|
group=$(printf '%s\n' "${group_array[@]%/}" | _rofi -dmenu -p "Choose Group > ")
|
||||||
|
if [[ $group == "" ]]; then
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
PASSWORD_STORE_DIR="${root}" pass mv "$selected_password" "${group}"
|
||||||
|
mainMenu
|
||||||
|
elif [[ $1 == "copy" ]]; then
|
||||||
|
cd "${root}" || exit
|
||||||
|
group_array=(*/)
|
||||||
|
group=$(printf '%s\n' "${group_array[@]%/}" | _rofi -dmenu -p "Choose Group > ")
|
||||||
|
if [[ $group == "" ]]; then
|
||||||
|
exit
|
||||||
|
else
|
||||||
|
new_name="$(listgpg | _rofi -dmenu -format 'f' -mesg "Copying to same Group. Please enter a name for the new entry" -p "> ")"
|
||||||
|
fi
|
||||||
|
PASSWORD_STORE_DIR="${root}" pass cp "$selected_password" "${group}/${new_name}"
|
||||||
|
mainMenu
|
||||||
|
elif [[ "$1" == "delete" ]]; then
|
||||||
|
HELP="<span color='$help_color'>Selected entry: ${selected_password}</span>"
|
||||||
|
ask_content=("Yes"
|
||||||
|
"No"
|
||||||
|
)
|
||||||
|
ask=$(printf '%s\n' "${ask_content[@]}" | _rofi -mesg "${HELP}" -dmenu -p "Are You Sure? > ")
|
||||||
|
if [[ "$ask" == "Yes" ]]; then
|
||||||
|
PASSWORD_STORE_DIR="${root}" pass rm --force "${selected_password}"
|
||||||
|
elif [[ "$ask" == "No" ]]; then
|
||||||
|
mainMenu
|
||||||
|
elif [[ -z "$ask" ]]; then
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
mainMenu
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
edit_pass() {
|
||||||
|
if [[ $edit_new_pass == "true" ]]; then
|
||||||
|
PASSWORD_STORE_DIR="${root}" pass edit "${1}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
insertPass () {
|
||||||
|
url=$(_clip_out_clipboard)
|
||||||
|
|
||||||
|
if [[ "${url:0:4}" == "http" ]]; then
|
||||||
|
domain_name="$(printf '%s\n' "${url}" | awk -F / '{l=split($3,a,"."); print (a[l-1]=="com"?a[l-2] OFS:X) a[l-1] OFS a[l]}' OFS=".")"
|
||||||
|
help_content="Domain: ${domain_name}
|
||||||
|
Type name, make sure it is unique"
|
||||||
|
else
|
||||||
|
help_content="Hint: Copy URL to clipboard before calling this menu.
|
||||||
|
Type name, make sure it is unique"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "${root}" || exit
|
||||||
|
group_array=(*/)
|
||||||
|
grouplist=$(printf '%s\n' "${group_array[@]%/}")
|
||||||
|
name="$(listgpg | _rofi -dmenu -format 'f' -filter "${domain_name}" -mesg "${help_content}" -p "> ")"
|
||||||
|
val=$?
|
||||||
|
|
||||||
|
if [[ $val -eq 1 ]]; then
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
user_content=("${default_user2}"
|
||||||
|
"${USER}"
|
||||||
|
"${default_user}"
|
||||||
|
)
|
||||||
|
|
||||||
|
user=$(printf '%s\n' "${user_content[@]}" | _rofi -dmenu -mesg "Chose Username or type" -p "> ")
|
||||||
|
val=$?
|
||||||
|
|
||||||
|
if [[ $val -eq 1 ]]; then
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
group_content=("No Group"
|
||||||
|
"---"
|
||||||
|
"${grouplist}"
|
||||||
|
)
|
||||||
|
|
||||||
|
group=$(printf '%s\n' "${group_content[@]}" | _rofi -dmenu -p "Choose Group > ")
|
||||||
|
val=$?
|
||||||
|
|
||||||
|
if [[ $val -eq 1 ]]; then
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
pw=$(printf '%s' "Generate" | _rofi -dmenu -password -p "Password > " -mesg "Type Password or hit Enter to generate one")
|
||||||
|
|
||||||
|
if [[ $pw == "Generate" ]]; then
|
||||||
|
pw=$(_pwgen "${password_length}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
clear
|
||||||
|
|
||||||
|
if [[ "$group" == "No Group" ]]; then
|
||||||
|
if [[ $url == http* ]]; then
|
||||||
|
pass_content=("${pw}"
|
||||||
|
"---"
|
||||||
|
"${USERNAME_field}: ${user}"
|
||||||
|
"${URL_field}: ${url}"
|
||||||
|
)
|
||||||
|
printf '%s\n' "${pass_content[@]}" | PASSWORD_STORE_DIR="${root}" pass insert -m "${name}" > /dev/null && edit_pass "${name}"
|
||||||
|
else
|
||||||
|
pass_content=("${pw}"
|
||||||
|
"---"
|
||||||
|
"${USERNAME_field}: ${user}"
|
||||||
|
)
|
||||||
|
printf '%s\n' "${pass_content[@]}" | PASSWORD_STORE_DIR="${root}" pass insert -m "${name}" > /dev/null && edit_pass "${name}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [[ $url == http* ]]; then
|
||||||
|
pass_content=("${pw}"
|
||||||
|
"---"
|
||||||
|
"${USERNAME_field}: ${user}"
|
||||||
|
"${URL_field}: ${url}"
|
||||||
|
)
|
||||||
|
printf '%s\n' "${pass_content[@]}" | PASSWORD_STORE_DIR="${root}" pass insert -m "${group}/${name}" > /dev/null && edit_pass "${group}/${name}"
|
||||||
|
else
|
||||||
|
pass_content=("${pw}"
|
||||||
|
"---"
|
||||||
|
"${USERNAME_field}: ${user}"
|
||||||
|
)
|
||||||
|
printf '%s\n' "${pass_content[@]}" | PASSWORD_STORE_DIR="${root}" pass insert -m "${group}/${name}" > /dev/null && edit_pass "${group}/${name}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
help_msg () {
|
||||||
|
cat <<'EOF'
|
||||||
|
Usage:
|
||||||
|
rofi-pass [command]
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
--insert insert new entry to password store
|
||||||
|
--root set custom root directories (colon separated)
|
||||||
|
--last-used highlight last used item
|
||||||
|
--show-last show details of last used Entry
|
||||||
|
--bmarks start in bookmarks mode
|
||||||
|
|
||||||
|
rofi-pass version 1.5.3
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
get_config_file () {
|
||||||
|
configs=("$ROFI_PASS_CONFIG"
|
||||||
|
"$config_dir/rofi-pass/config"
|
||||||
|
"/etc/rofi-pass.conf")
|
||||||
|
|
||||||
|
# return the first config file with a valid path
|
||||||
|
for config in "${configs[@]}"; do
|
||||||
|
# '-n' is needed in case ROFI_PASS_CONFIG is not set
|
||||||
|
if [[ -n "${config}" && -f "${config}" ]]; then
|
||||||
|
printf "%s" "$config"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
main () {
|
||||||
|
# load config file
|
||||||
|
config_file="$(get_config_file)"
|
||||||
|
[[ -n "$config_file" ]] && source "$config_file"
|
||||||
|
|
||||||
|
# create tmp dir
|
||||||
|
if [[ ! -d "$cache_dir/rofi-pass" ]]; then
|
||||||
|
mkdir -p "$cache_dir/rofi-pass"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# fix keyboard layout if enabled in config
|
||||||
|
if [[ $fix_layout == "true" ]]; then
|
||||||
|
layout_cmd
|
||||||
|
fi
|
||||||
|
|
||||||
|
# set help color
|
||||||
|
if [[ $help_color == "" ]]; then
|
||||||
|
help_color=$(rofi -dump-xresources | grep 'rofi.color.normal' | gawk -F ',' '/,/{gsub(/ /, "", $2); print $2}')
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check for BROWSER variable, use xdg-open as fallback
|
||||||
|
if [[ -z $BROWSER ]]; then
|
||||||
|
export BROWSER=xdg-open
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check if alternative root directory was given on commandline
|
||||||
|
if [[ -r "$cache_dir/rofi-pass/last_used" ]] && [[ $1 == "--last-used" || $1 == "--show-last" ]]; then
|
||||||
|
roots=("$(awk -F ': ' '{ print $1 }' "$cache_dir/rofi-pass/last_used")")
|
||||||
|
elif [[ -n "$2" && "$1" == "--root" ]]; then
|
||||||
|
custom_root=true; IFS=: read -r -a roots <<< "$2"
|
||||||
|
elif [[ -n $root ]]; then
|
||||||
|
custom_root=true; IFS=: read -r -a roots <<< "${root}"
|
||||||
|
elif [[ -n ${PASSWORD_STORE_DIR} ]]; then
|
||||||
|
roots=("${PASSWORD_STORE_DIR}")
|
||||||
|
else
|
||||||
|
roots=("$HOME/.password-store")
|
||||||
|
fi
|
||||||
|
roots_index=0
|
||||||
|
roots_length=${#roots[@]}
|
||||||
|
export root=${roots[$roots_index]}
|
||||||
|
export PASSWORD_STORE_DIR="${root}"
|
||||||
|
case $1 in
|
||||||
|
--insert)
|
||||||
|
insertPass
|
||||||
|
;;
|
||||||
|
--root)
|
||||||
|
mainMenu
|
||||||
|
;;
|
||||||
|
--help)
|
||||||
|
help_msg
|
||||||
|
;;
|
||||||
|
--last-used)
|
||||||
|
if [[ -r "$cache_dir/rofi-pass/last_used" ]]; then
|
||||||
|
entry="$(awk -F ': ' '{ print $2 }' "$cache_dir/rofi-pass/last_used")"
|
||||||
|
fi
|
||||||
|
mainMenu
|
||||||
|
;;
|
||||||
|
--show-last)
|
||||||
|
if [[ -r "$cache_dir/rofi-pass/last_used" ]]; then
|
||||||
|
selected_password="$(awk -F ': ' '{ print $2 }' "$cache_dir/rofi-pass/last_used")" viewEntry
|
||||||
|
else
|
||||||
|
mainMenu
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
--bmarks)
|
||||||
|
mainMenu --bmarks;
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
mainMenu
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
184
home/.local/usr/bin/rofi-screenshot
Executable file
184
home/.local/usr/bin/rofi-screenshot
Executable file
@@ -0,0 +1,184 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
## rofi-screenshot
|
||||||
|
## Author: ceuk @ github
|
||||||
|
## Licence: WTFPL
|
||||||
|
## Usage:
|
||||||
|
## show the menu with rofi-screenshot
|
||||||
|
## stop recording with rofi-screenshot -s
|
||||||
|
|
||||||
|
# Screenshot directory
|
||||||
|
screenshot_directory="/home/raelon/Pictures/Screenshots"
|
||||||
|
|
||||||
|
# set ffmpeg defaults
|
||||||
|
ffmpeg() {
|
||||||
|
command ffmpeg -hide_banner -loglevel error -nostdin "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
video_to_gif() {
|
||||||
|
ffmpeg -i "$1" -vf palettegen -f image2 -c:v png - |
|
||||||
|
ffmpeg -i "$1" -i - -filter_complex paletteuse "$2"
|
||||||
|
}
|
||||||
|
|
||||||
|
countdown() {
|
||||||
|
notify-send "Screenshot" "Recording in 3 seconds" -t 1000
|
||||||
|
sleep 1
|
||||||
|
notify-send "Screenshot" "Recording in 2 seconds" -t 1000
|
||||||
|
sleep 1
|
||||||
|
notify-send "Screenshot" "Recording in 1 seconds" -t 1000
|
||||||
|
sleep 1
|
||||||
|
}
|
||||||
|
|
||||||
|
crtc() {
|
||||||
|
notify-send "Screenshot" "Select a region to capture"
|
||||||
|
ffcast -q $(slop -n -f '%g ') png /tmp/screenshot_clip.png
|
||||||
|
xclip -selection clipboard -t image/png /tmp/screenshot_clip.png
|
||||||
|
rm /tmp/screenshot_clip.png
|
||||||
|
notify-send "Screenshot" "Region copied to Clipboard"
|
||||||
|
}
|
||||||
|
|
||||||
|
crtf() {
|
||||||
|
notify-send "Screenshot" "Select a region to capture"
|
||||||
|
dt=$(date '+%d-%m-%Y %H:%M:%S')
|
||||||
|
ffcast -q $(slop -n -f '%g ') png "$screenshot_directory/$dt.png"
|
||||||
|
notify-send "Screenshot" "Region saved to $screenshot_directory"
|
||||||
|
}
|
||||||
|
|
||||||
|
cstc() {
|
||||||
|
ffcast -q png /tmp/screenshot_clip.png
|
||||||
|
xclip -selection clipboard -t image/png /tmp/screenshot_clip.png
|
||||||
|
rm /tmp/screenshot_clip.png
|
||||||
|
notify-send "Screenshot" "Screenshot copied to Clipboard"
|
||||||
|
}
|
||||||
|
|
||||||
|
cstf() {
|
||||||
|
dt=$(date '+%d-%m-%Y %H:%M:%S')
|
||||||
|
ffcast -q png "$screenshot_directory/$dt.png"
|
||||||
|
notify-send "Screenshot" "Screenshot saved to $screenshot_directory"
|
||||||
|
}
|
||||||
|
|
||||||
|
rgrtf() {
|
||||||
|
notify-send "Screenshot" "Select a region to record"
|
||||||
|
dt=$(date '+%d-%m-%Y %H:%M:%S')
|
||||||
|
ffcast -q $(slop -n -f '%g ' && countdown) rec /tmp/screenshot_gif.mp4
|
||||||
|
notify-send "Screenshot" "Converting to gif... (this can take a while)"
|
||||||
|
video_to_gif /tmp/screenshot_gif.mp4 "$screenshot_directory/$dt.gif"
|
||||||
|
rm /tmp/screenshot_gif.mp4
|
||||||
|
notify-send "Screenshot" "Recording saved to $screenshot_directory"
|
||||||
|
}
|
||||||
|
|
||||||
|
rgstf() {
|
||||||
|
countdown
|
||||||
|
dt=$(date '+%d-%m-%Y %H:%M:%S')
|
||||||
|
ffcast -q rec /tmp/screenshot_gif.mp4
|
||||||
|
notify-send "Screenshot" "Converting to gif... (this can take a while)"
|
||||||
|
video_to_gif /tmp/screenshot_gif.mp4 "$screenshot_directory/$dt.gif"
|
||||||
|
rm /tmp/screenshot_gif.mp4
|
||||||
|
notify-send "Screenshot" "Recording saved to $screenshot_directory"
|
||||||
|
}
|
||||||
|
|
||||||
|
rvrtf() {
|
||||||
|
notify-send "Screenshot" "Select a region to record"
|
||||||
|
dt=$(date '+%d-%m-%Y %H:%M:%S')
|
||||||
|
ffcast -q $(slop -n -f '%g ' && countdown) rec "$screenshot_directory/$dt.mp4"
|
||||||
|
notify-send "Screenshot" "Recording saved to $screenshot_directory"
|
||||||
|
}
|
||||||
|
|
||||||
|
rvstf() {
|
||||||
|
countdown
|
||||||
|
dt=$(date '+%d-%m-%Y %H:%M:%S')
|
||||||
|
ffcast -q rec "$screenshot_directory/$dt.mp4"
|
||||||
|
notify-send "Screenshot" "Recording saved to $screenshot_directory"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_options() {
|
||||||
|
echo " Capture Region Clip"
|
||||||
|
echo " Capture Region File"
|
||||||
|
echo " Capture Screen Clip"
|
||||||
|
echo " Capture Screen File"
|
||||||
|
echo " Record Region File (GIF)"
|
||||||
|
echo " Record Screen File (GIF)"
|
||||||
|
echo " Record Region File (MP4)"
|
||||||
|
echo " Record Screen File (MP4)"
|
||||||
|
}
|
||||||
|
|
||||||
|
check_deps() {
|
||||||
|
if ! hash $1 2>/dev/null; then
|
||||||
|
echo "Error: This script requires $1"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
# check dependencies
|
||||||
|
check_deps slop
|
||||||
|
check_deps ffcast
|
||||||
|
check_deps ffmpeg
|
||||||
|
check_deps xclip
|
||||||
|
check_deps rofi
|
||||||
|
|
||||||
|
if [[ $1 == '--help' ]] || [[ $1 = '-h' ]]
|
||||||
|
then
|
||||||
|
echo ### rofi-screenshot
|
||||||
|
echo USAGE: rofi-screenshot [OPTION]
|
||||||
|
echo \(no option\)
|
||||||
|
echo " show the screenshot menu"
|
||||||
|
echo -s, --stop
|
||||||
|
echo " stop recording"
|
||||||
|
echo -h, --help
|
||||||
|
echo " this screen"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $1 = '--stop' ]] || [[ $1 = '-s' ]]
|
||||||
|
then
|
||||||
|
pkill -fxn '(/\S+)*ffmpeg\s.*\sx11grab\s.*'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get choice from rofi
|
||||||
|
choice=$( (get_options) | rofi -dmenu -i -fuzzy -p "Screenshot" )
|
||||||
|
|
||||||
|
# If user has not picked anything, exit
|
||||||
|
if [[ -z "${choice// }" ]]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# run the selected command
|
||||||
|
case $choice in
|
||||||
|
' Capture Region Clip')
|
||||||
|
crtc
|
||||||
|
;;
|
||||||
|
' Capture Region File')
|
||||||
|
crtf
|
||||||
|
;;
|
||||||
|
' Capture Screen Clip')
|
||||||
|
cstc
|
||||||
|
;;
|
||||||
|
' Capture Screen File')
|
||||||
|
cstf
|
||||||
|
;;
|
||||||
|
' Record Region File (GIF)')
|
||||||
|
rgrtf
|
||||||
|
;;
|
||||||
|
' Record Screen File (GIF)')
|
||||||
|
rgstf
|
||||||
|
;;
|
||||||
|
' Record Region File (MP4)')
|
||||||
|
rvrtf
|
||||||
|
;;
|
||||||
|
' Record Screen File (MP4)')
|
||||||
|
rvstf
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# done
|
||||||
|
set -e
|
||||||
|
}
|
||||||
|
|
||||||
|
main $1 &
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
!/bin/bash
|
||||||
|
|
||||||
2
home/.local/usr/bin/screenshot
Executable file
2
home/.local/usr/bin/screenshot
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
scrot ~/Pictures/Screenshots/'%y%m%d-%H:%M'.png -f -s -e 'xclip -selection clipboard -t image/png -i $f'
|
||||||
47
home/.local/usr/bin/screenshot.sh
Executable file
47
home/.local/usr/bin/screenshot.sh
Executable file
@@ -0,0 +1,47 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#changelog
|
||||||
|
#v0.3
|
||||||
|
#added 1. Notifications 2.unique names for each type (for quick launch) 3.better photo editor (pinta) 4.dmenu title
|
||||||
|
#v0.4
|
||||||
|
#1.Added variable for notification timeouts. 2. Show link in notification
|
||||||
|
|
||||||
|
|
||||||
|
IMG_PATH=$HOME/Pictures/Screenshots
|
||||||
|
UL=fb
|
||||||
|
EDIT=gimp
|
||||||
|
TIME=3000 #Miliseconds notification should remain visible
|
||||||
|
|
||||||
|
|
||||||
|
prog="
|
||||||
|
---Local screenshots (saved at IMG_PATH)---
|
||||||
|
1.quick_fullscreen
|
||||||
|
2.delayed_fullscreen
|
||||||
|
3.section
|
||||||
|
4.edit_fullscreen
|
||||||
|
---Upload to remote service (images will be deleted)---
|
||||||
|
a.upload_fullscreen
|
||||||
|
u.upload_delayed_fullscreen
|
||||||
|
e.edit_upload_fullscreen
|
||||||
|
s.upload_section
|
||||||
|
p.edit_upload_section
|
||||||
|
"
|
||||||
|
|
||||||
|
cmd=$(dmenu -l 20 -nf '#999' -nb '#292d3e' -sf '#eee' -sb '#0077bb' -p 'Choose Screenshot Type' <<< "$prog")
|
||||||
|
|
||||||
|
cd $IMG_PATH
|
||||||
|
case ${cmd%% *} in
|
||||||
|
|
||||||
|
1.quick_fullscreen) scrot -d 1 '%Y-%m-%d-@%H-%M-%S-scrot.png' && notify-send -u low -t $TIME 'Scrot' 'Fullscreen taken and saved' ;;
|
||||||
|
2.delayed_fullscreen) scrot -d 4 '%Y-%m-%d-@%H-%M-%S-scrot.png' && notify-send -u low -t $TIME 'Scrot' 'Fullscreen Screenshot saved' ;;
|
||||||
|
3.section) scrot -s '%Y-%m-%d-@%H-%M-%S-scrot.png' && notify-send -u low -t $TIME 'Scrot' 'Screenshot of section saved' ;;
|
||||||
|
4.edit_fullscreen) scrot -d 1 '%Y-%m-%d-@%H-%M-%S-scrot.png' -e "$EDIT \$f" && notify-send -u low -t $TIME 'Scrot' 'Screenshot edited and saved' ;;
|
||||||
|
|
||||||
|
a.upload_fullscreen) scrot -d 1 '%Y-%m-%d-@%H-%M-%S-scrot.png' -e "$UL \$f" && (xclip -o;echo) | xclip -selection clipboard && notify-send -u low -t $TIME "Scrot" "Screenshot Uploaded (powered by fb) - $(xclip -o;echo)" ;;
|
||||||
|
u.upload_delayed_fullscreen) scrot -d 4 '%Y-%m-%d-@%H-%M-%S-scrot.png' -e "$UL \$f" && (xclip -o;echo) | xclip -selection clipboard && notify-send -u low -t $TIME "Scrot" "Screenshot Uploaded (powered by fb) - $(xclip -o)" ;;
|
||||||
|
e.edit_upload_fullscreen) scrot -d 4 '%Y-%m-%d-@%H-%M-%S-scrot.png' -e "$EDIT \$f && $UL \$f && rm -f \$f" && notify-send -u low -t $TIME "Scrot" "Screenshot Uploaded (powered by fb) - $(xclip -o)" ;;
|
||||||
|
s.upload_section) scrot -s '%Y-%m-%d-@%H-%M-%S-scrot.png' -e "$UL \$f" && (xclip -o;echo) | xclip -selection clipboard && notify-send -u low -t $TIME "Scrot" "Screenshot Uploaded (powered by fb - $(xclip -o)";;
|
||||||
|
p.edit_upload_section) scrot -s '%Y-%m-%d-@%H-%M-%S-scrot.png' -e "$EDIT \$f && $UL \$f && rm -f \$f" && (xclip -o;echo) | xclip -selection clipboard && notify-send -u low -t $TIME "Scrot" "Screenshot Uploaded (powered by FB) - $(xclip -o)" ;;
|
||||||
|
|
||||||
|
|
||||||
|
*) exec "'${cmd}'" ;;
|
||||||
|
esac
|
||||||
33
home/.local/usr/bin/surf-open.sh
Executable file
33
home/.local/usr/bin/surf-open.sh
Executable file
@@ -0,0 +1,33 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# See the LICENSE file for copyright and license details.
|
||||||
|
#
|
||||||
|
|
||||||
|
# xidfile="$HOME/tmp/tabbed-surf.xid"
|
||||||
|
xidfile="$HOME/.local/state/tabbed-surf.xid"
|
||||||
|
uri="https://duckduckgo.com/lite"
|
||||||
|
|
||||||
|
if [ "$#" -gt 0 ];
|
||||||
|
then
|
||||||
|
uri="$1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
runtabbed() {
|
||||||
|
tabbed -dn tabbed-surf -r 2 surf -e '' "$uri" >"$xidfile" \
|
||||||
|
2>/dev/null &
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ ! -r "$xidfile" ];
|
||||||
|
then
|
||||||
|
runtabbed
|
||||||
|
else
|
||||||
|
xid=$(cat "$xidfile")
|
||||||
|
xprop -id "$xid" >/dev/null 2>&1
|
||||||
|
if [ $? -gt 0 ];
|
||||||
|
then
|
||||||
|
runtabbed
|
||||||
|
else
|
||||||
|
surf -e "$xid" "$uri" >/dev/null 2>&1 &
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
4
home/.local/usr/bin/swapesc.sh
Executable file
4
home/.local/usr/bin/swapesc.sh
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Swap ESC and Caps Lock
|
||||||
|
eval "setxkbmap -option caps:swapescape"
|
||||||
34
home/.local/usr/bin/taskadd
Executable file
34
home/.local/usr/bin/taskadd
Executable file
@@ -0,0 +1,34 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Behavior:
|
||||||
|
# Userscript for qutebrowser which adds a task to taskwarrior.
|
||||||
|
# If run as a command (:spawn --userscript taskadd), it creates a new task
|
||||||
|
# with the description equal to the current page title and annotates it with
|
||||||
|
# the current page url. Additional arguments are passed along so you can add
|
||||||
|
# mods to the task (e.g. priority, due date, tags).
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# :spawn --userscript taskadd due:eod pri:H
|
||||||
|
#
|
||||||
|
# To enable passing along extra args, I suggest using a mapping like:
|
||||||
|
# :bind <somekey> cmd-set-text -s :spawn --userscript taskadd
|
||||||
|
#
|
||||||
|
# If run from hint mode, it uses the selected hint text as the description
|
||||||
|
# and the selected hint url as the annotation.
|
||||||
|
#
|
||||||
|
# Ryan Roden-Corrent (rcorre), 2016
|
||||||
|
# Any feedback is welcome!
|
||||||
|
#
|
||||||
|
# For more info on Taskwarrior, see https://taskwarrior.org/
|
||||||
|
|
||||||
|
# use either the current page title or the hint text as the task description
|
||||||
|
[[ $QUTE_MODE == 'hints' ]] && title=$QUTE_SELECTED_TEXT || title=$QUTE_TITLE
|
||||||
|
|
||||||
|
# try to add the task and grab the output
|
||||||
|
if msg="$(task add "$title" "$*" 2>&1)"; then
|
||||||
|
# annotate the new task with the url, send the output back to the browser
|
||||||
|
task +LATEST annotate "$QUTE_URL"
|
||||||
|
echo "message-info '$(echo "$msg" | head -n 1)'" >> "$QUTE_FIFO"
|
||||||
|
else
|
||||||
|
echo "message-error '$(echo "$msg" | head -n 1)'" >> "$QUTE_FIFO"
|
||||||
|
fi
|
||||||
24
home/.local/usr/bin/tmuxsessions.sh
Executable file
24
home/.local/usr/bin/tmuxsessions.sh
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Description: A script to list and start tmuxinator projects using fzf.
|
||||||
|
|
||||||
|
# Set the directory where your tmuxinator configuration files are located
|
||||||
|
TMUXINATOR_CONFIG_DIR="${HOME}/.config/tmuxinator/"
|
||||||
|
|
||||||
|
# Find all tmuxinator `.yml` files in the specified directory, remove path and extensions
|
||||||
|
# project=$(find "$TMUXINATOR_CONFIG_DIR" -type f -name "*.yml" | sed 's|.*/||;s|\.yml$||' | \
|
||||||
|
# fzf --prompt="Session: " --preview-label="pyTui Tmuxinator Picker" --preview-label-pos=bottom \
|
||||||
|
# --preview="bat --style=full --color=always" --preview-window=up \
|
||||||
|
# )
|
||||||
|
|
||||||
|
# project=$(find "$TMUXINATOR_CONFIG_DIR" -type f -name "*.yml" | sed 's|.*/||;s|\.yml$||' | fzf --prompt="Session: " --tmux bottom,5%)
|
||||||
|
project=$(find "$TMUXINATOR_CONFIG_DIR" -type f -name "*.yml" | sed 's|.*/||;s|\.yml$||' | fzf --prompt="Session " --tmux left,25 --reverse)
|
||||||
|
|
||||||
|
# Check if a project was selected
|
||||||
|
if [[ -n "$project" ]]; then
|
||||||
|
# Start the selected tmuxinator project
|
||||||
|
tmuxinator start "$project"
|
||||||
|
# else
|
||||||
|
# echo "No project selected. Exiting..."
|
||||||
|
# exit 1
|
||||||
|
fi
|
||||||
6
home/.local/usr/bin/tmuxstartup.sh
Executable file
6
home/.local/usr/bin/tmuxstartup.sh
Executable file
@@ -0,0 +1,6 @@
|
|||||||
|
#!/usr/bin/bash
|
||||||
|
|
||||||
|
fastfetch --logo small --structure "title:os:kernel:cpu:memory:disk:uptime"
|
||||||
|
misfortune|cowsay|lolcat
|
||||||
|
|
||||||
|
exec zsh
|
||||||
6
home/.local/usr/bin/touchpad
Executable file
6
home/.local/usr/bin/touchpad
Executable file
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
idd=$(xinput --list | grep "DELL07E6:00 06CB:76AF Touchpad" | awk '{print $6}' | cut -d'=' -f2)
|
||||||
|
sudo xinput set-prop $idd 318 1
|
||||||
|
sudo xinput set-prop $idd 300 1
|
||||||
|
sudo xinput set-prop $idd 307 1
|
||||||
|
sudo xinput set-prop $idd 309 .5
|
||||||
120
home/.local/usr/bin/url_handler.sh
Executable file
120
home/.local/usr/bin/url_handler.sh
Executable file
@@ -0,0 +1,120 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
# Copyright (c) 1998 Martin Schulze <joey@debian.org>
|
||||||
|
# Slightly modified by Luis Francisco Gonzalez <luisgh@debian.org>
|
||||||
|
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
###########################################################################
|
||||||
|
# Configurable section
|
||||||
|
###########################################################################
|
||||||
|
#
|
||||||
|
# Any entry in the lists of programs that urlview handler will try out will
|
||||||
|
# be made of /path/to/program + ':' + TAG where TAG is one of
|
||||||
|
# XW: XWindows program
|
||||||
|
# XT: Launch with an xterm if possible or as VT if not
|
||||||
|
# VT: Launch in the same terminal
|
||||||
|
|
||||||
|
# The lists of programs to be executed are
|
||||||
|
https_prgs="/usr/bin/qutebrowser:XW /usr/bin/w3m:XT"
|
||||||
|
http_prgs="/usr/bin/qutebrowser:XW /usr/bin/w3m:XT"
|
||||||
|
mailto_prgs="/usr/bin/neomutt:VT /usr/bin/elm:VT /usr/bin/pine:VT /usr/bin/mail:VT"
|
||||||
|
gopher_prgs="/usr/bin/lynx:XT /usr/bin/gopher:XT"
|
||||||
|
ftp_prgs="/usr/bin/ranger:XT /usr/bin/ncftp:XT"
|
||||||
|
|
||||||
|
# Program used as an xterm (if it doesn't support -T you'll need to change
|
||||||
|
# the command line in getprg)
|
||||||
|
XTERM=/usr/bin/kitty
|
||||||
|
|
||||||
|
|
||||||
|
###########################################################################
|
||||||
|
# Change bellow this at your own risk
|
||||||
|
###########################################################################
|
||||||
|
function getprg()
|
||||||
|
{
|
||||||
|
local ele tag prog
|
||||||
|
|
||||||
|
for ele in $*
|
||||||
|
do
|
||||||
|
tag=${ele##*:}
|
||||||
|
prog=${ele%%:*}
|
||||||
|
if [ -x $prog ]; then
|
||||||
|
case $tag in
|
||||||
|
XW)
|
||||||
|
[ -n "$DISPLAY" ] && echo "X:$prog" && return 0
|
||||||
|
;;
|
||||||
|
XT)
|
||||||
|
[ -n "$DISPLAY" ] && [ -x "$XTERM" ] && \
|
||||||
|
echo "X:$XTERM -e $prog" && return 0
|
||||||
|
echo "$prog" && return 0
|
||||||
|
;;
|
||||||
|
VT)
|
||||||
|
echo "$prog" && return 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
url="$1"; shift
|
||||||
|
|
||||||
|
type="${url%%:*}"
|
||||||
|
|
||||||
|
if [ "$url" = "$type" ]; then
|
||||||
|
type="${url%%.*}"
|
||||||
|
case "$type" in
|
||||||
|
www|web)
|
||||||
|
type=http
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
url="$type://$url"
|
||||||
|
fi
|
||||||
|
|
||||||
|
case $type in
|
||||||
|
https)
|
||||||
|
prg=`getprg $https_prgs`
|
||||||
|
;;
|
||||||
|
http)
|
||||||
|
prg=`getprg $http_prgs`
|
||||||
|
;;
|
||||||
|
ftp)
|
||||||
|
prg=`getprg $ftp_prgs`
|
||||||
|
;;
|
||||||
|
mailto)
|
||||||
|
prg=`getprg $mailto_prgs`
|
||||||
|
url="${url#mailto:}"
|
||||||
|
;;
|
||||||
|
gopher)
|
||||||
|
prg=`getprg $gopher_prgs`
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown URL type. Please report URL and viewer to:"
|
||||||
|
echo "joey@debian.org."
|
||||||
|
echo -n "Press enter to continue."; read x
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -n "$prg" ]; then
|
||||||
|
if [ "${prg%:*}" = "X" ]; then
|
||||||
|
${prg#*:} "$url" 2>/dev/null &
|
||||||
|
else
|
||||||
|
$prg "$url"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
28
home/.local/usr/bin/win98
Executable file
28
home/.local/usr/bin/win98
Executable file
@@ -0,0 +1,28 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Enable basic sound output via pulseaudio
|
||||||
|
# Run "pacmd list-sinks | grep -e 'name:' -e 'index'" to find your QEMU_PA_SINK
|
||||||
|
export QEMU_AUDIO_DRV=pa
|
||||||
|
export QEMU_PA_SINK=alsa_output.pci-0000_00_1f.3.analog-stereo
|
||||||
|
export QEMU_PA_SOURCE=input
|
||||||
|
|
||||||
|
# Start QEMU
|
||||||
|
qemu-system-x86_64 \
|
||||||
|
-enable-kvm \
|
||||||
|
-m 3G \
|
||||||
|
-smp cores=2,threads=2,sockets=1,maxcpus=4 \
|
||||||
|
-cpu host,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time \
|
||||||
|
-machine type=pc,accel=kvm,kernel_irqchip=on \
|
||||||
|
-global PIIX4_PM.disable_s3=1 \
|
||||||
|
-global PIIX4_PM.disable_s4=1 \
|
||||||
|
-name windows-98-guest \
|
||||||
|
-cdrom '/home/raelon/isos/win98se.iso' \
|
||||||
|
-drive file='/home/raelon/usd/win98',format=qcow2,l2-cache-size=8M \
|
||||||
|
-boot order=d \
|
||||||
|
-soundhw hda \
|
||||||
|
-usb \
|
||||||
|
-device usb-tablet \
|
||||||
|
# -nic none \
|
||||||
|
-vga qxl \
|
||||||
|
-display gtk,gl=on \
|
||||||
|
-device vfio-pci,sysfsdev=/sys/devices/pci0000:00/0000:00:02.0/87c17a7c-972b-407a-b14a-74779f799b8d,x-igd-opregion=on,display=on \
|
||||||
41
home/.local/usr/lib/blightmud/empiremud.lua
Normal file
41
home/.local/usr/lib/blightmud/empiremud.lua
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
local mapfile = "/home/th3r00t/.local/share/blightmud/empiremud.map"
|
||||||
|
Map = Mapper.create("empiremud")
|
||||||
|
|
||||||
|
local function file_exists(file)
|
||||||
|
local f = io.open(file, "r")
|
||||||
|
if f then
|
||||||
|
f:close()
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function load_map()
|
||||||
|
if file_exists(mapfile) then
|
||||||
|
blight.status_line(1, "Loading map...")
|
||||||
|
Map:load(mapfile)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function empiremud_connect()
|
||||||
|
blight.status_height(1)
|
||||||
|
blight.status_line(0, "Connecting to Enpire Mud...")
|
||||||
|
blight.status_line(1, "Logging in...")
|
||||||
|
mud.send("Raelon")
|
||||||
|
mud.send("b2edxfrr1")
|
||||||
|
blight.status_line(1, "Connected To Enpire Mud.")
|
||||||
|
blight.status_line(0, "Enpire Mud")
|
||||||
|
load_map()
|
||||||
|
Map:print()
|
||||||
|
end
|
||||||
|
|
||||||
|
mud.on_disconnect(function()
|
||||||
|
blight.status_line(0, "Disconnected.")
|
||||||
|
if Map then
|
||||||
|
Map:save(mapfile)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
empiremud_connect()
|
||||||
40
home/.local/usr/lib/blightmud/sindome.lua
Normal file
40
home/.local/usr/lib/blightmud/sindome.lua
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
local mapfile = "/home/th3r00t/.local/share/blightmud/sindome.map"
|
||||||
|
Map = Mapper.create("sindome")
|
||||||
|
|
||||||
|
local function file_exists(file)
|
||||||
|
local f = io.open(file, "r")
|
||||||
|
if f then
|
||||||
|
f:close()
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function load_map()
|
||||||
|
if file_exists(mapfile) then
|
||||||
|
blight.status_line(1, "Loading map...")
|
||||||
|
Map:load(mapfile)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function sindome_connect()
|
||||||
|
blight.status_height(1)
|
||||||
|
blight.status_line(0, "Connecting to Sindome...")
|
||||||
|
blight.status_line(1, "Logging in...")
|
||||||
|
mud.send("connect ryn XeGEb")
|
||||||
|
blight.status_line(1, "Connected To Sindome.")
|
||||||
|
blight.status_line(0, "Sindome")
|
||||||
|
load_map()
|
||||||
|
Map:print()
|
||||||
|
end
|
||||||
|
|
||||||
|
mud.on_disconnect(function()
|
||||||
|
blight.status_line(0, "Disconnected.")
|
||||||
|
if Map then
|
||||||
|
Map:save(mapfile)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
sindome_connect()
|
||||||
40
home/.local/usr/lib/blightmud/untold-dawn.lua
Normal file
40
home/.local/usr/lib/blightmud/untold-dawn.lua
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
local mapfile = "/home/th3r00t/.local/share/blightmud/sindome.map"
|
||||||
|
Map = Mapper.create("untolddawn")
|
||||||
|
|
||||||
|
local function file_exists(file)
|
||||||
|
local f = io.open(file, "r")
|
||||||
|
if f then
|
||||||
|
f:close()
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function load_map()
|
||||||
|
if file_exists(mapfile) then
|
||||||
|
blight.status_line(1, "Loading map...")
|
||||||
|
Map:load(mapfile)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function untolddawn_connect()
|
||||||
|
blight.status_height(1)
|
||||||
|
blight.status_line(0, "Connecting to Untold Dawn...")
|
||||||
|
blight.status_line(1, "Logging in...")
|
||||||
|
mud.send("login th3r00t b2edxfrr1")
|
||||||
|
blight.status_line(1, "Connected To Untold Dawn.")
|
||||||
|
blight.status_line(0, "Untold Dawn")
|
||||||
|
load_map()
|
||||||
|
Map:print()
|
||||||
|
end
|
||||||
|
|
||||||
|
mud.on_disconnect(function()
|
||||||
|
blight.status_line(0, "Disconnected.")
|
||||||
|
if Map then
|
||||||
|
Map:save(mapfile)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
untolddawn_connect()
|
||||||
49
home/.taskrc
Normal file
49
home/.taskrc
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# [Created by task 2.6.2 7/28/2022 12:49:42]
|
||||||
|
# Taskwarrior program configuration file.
|
||||||
|
# For more documentation, see https://taskwarrior.org or try 'man task', 'man task-color',
|
||||||
|
# 'man task-sync' or 'man taskrc'
|
||||||
|
|
||||||
|
# Here is an example of entries that use the default, override and blank values
|
||||||
|
# variable=foo -- By specifying a value, this overrides the default
|
||||||
|
# variable= -- By specifying no value, this means no default
|
||||||
|
# #variable=foo -- By commenting out the line, or deleting it, this uses the default
|
||||||
|
|
||||||
|
# You can also refence environment variables:
|
||||||
|
# variable=$HOME/task
|
||||||
|
# variable=$VALUE
|
||||||
|
|
||||||
|
# Use the command 'task show' to see all defaults and overrides
|
||||||
|
|
||||||
|
# Files
|
||||||
|
data.location=/home/th3r00t/.task
|
||||||
|
|
||||||
|
# To use the default location of the XDG directories,
|
||||||
|
# move this configuration file from ~/.taskrc to ~/.config/task/taskrc and uncomment below
|
||||||
|
|
||||||
|
#data.location=~/.local/share/task
|
||||||
|
#hooks.location=~/.config/task/hooks
|
||||||
|
|
||||||
|
# Color theme (uncomment one to use)
|
||||||
|
#include light-16.theme
|
||||||
|
#include light-256.theme
|
||||||
|
#include dark-16.theme
|
||||||
|
#include dark-256.theme
|
||||||
|
#include dark-red-256.theme
|
||||||
|
#include dark-green-256.theme
|
||||||
|
include dark-blue-256.theme
|
||||||
|
#include dark-violets-256.theme
|
||||||
|
#include dark-yellow-green.theme
|
||||||
|
#include dark-gray-256.theme
|
||||||
|
#include dark-gray-blue-256.theme
|
||||||
|
#include solarized-dark-256.theme
|
||||||
|
#include solarized-light-256.theme
|
||||||
|
#include no-color.theme
|
||||||
|
#taskd.trust=allow all
|
||||||
|
taskd.server=mylt.dev:53589
|
||||||
|
taskd.credentials=own\/th3r00t\/cc06caef-20ea-48e6-8d61-23ac7d12941a
|
||||||
|
taskd.certificate=/home/th3r00t/.task/th3r00t.cert.pem
|
||||||
|
taskd.key=/home/th3r00t/.task/th3r00t.key.pem
|
||||||
|
taskd.ca=/home/th3r00t/.task/ca.cert.pem
|
||||||
|
|
||||||
|
#include ~/.local/builds/falcon/taskwarrior/falcon.theme
|
||||||
|
news.version=3.1.0
|
||||||
1350
home/config/dosbox-x/dosbox-x-2025.05.03.conf
Normal file
1350
home/config/dosbox-x/dosbox-x-2025.05.03.conf
Normal file
File diff suppressed because it is too large
Load Diff
138
home/config/nvim/init.lua
Normal file
138
home/config/nvim/init.lua
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
local vim = vim
|
||||||
|
require("options") -- lua/options.lua
|
||||||
|
require("plugins") -- lua/plugins.lua
|
||||||
|
require("utils.t3_functions") -- lua/utils/t3_functions.lua
|
||||||
|
require("utils.t3_overrides") -- lua/utils/t3_overrides.lua
|
||||||
|
require("utils.reload") -- lua/utils/reload.lua
|
||||||
|
require("vimwiki") -- lua/vimwiki.lua
|
||||||
|
require("keymaps") -- lua/keymaps.lua
|
||||||
|
require("lsp") -- lua/lsp.lua
|
||||||
|
require("completion") -- lua/completion.lua
|
||||||
|
require("treesitter") -- lua/treesitter.lua
|
||||||
|
require("autocmds") -- lua/autocmds.lua
|
||||||
|
require("diagnostics") -- lua/diagnostics.lua
|
||||||
|
|
||||||
|
require('tokyonight').setup({
|
||||||
|
style = "moon", -- "storm", "moon", "day", "night"
|
||||||
|
transparent = true, -- Enable transparent background
|
||||||
|
terminal_colors = true, -- Enable terminal colors
|
||||||
|
styles = {
|
||||||
|
comments = { italic = true }, -- Italic comments
|
||||||
|
keywords = { italic = true }, -- Italic keywords
|
||||||
|
functions = { bold = true }, -- Bold functions
|
||||||
|
variables = {}, -- No special style for variables
|
||||||
|
sidebars = "dark", -- Dark sidebars
|
||||||
|
floats = "dark", -- Dark floating windows
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
local function is_linux_console()
|
||||||
|
return vim.env.TERM == "linux"
|
||||||
|
end
|
||||||
|
|
||||||
|
local function want_truecolor()
|
||||||
|
if is_linux_console() then return false end
|
||||||
|
return vim.fn.has("termguicolors") == 1
|
||||||
|
or ((vim.env.COLORTERM or ""):lower():find("truecolor") ~= nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function set_colorscheme()
|
||||||
|
if want_truecolor() then
|
||||||
|
vim.o.termguicolors = true
|
||||||
|
if not pcall(vim.cmd.colorscheme, "tokyonight") then
|
||||||
|
pcall(vim.cmd.colorscheme, "habamax")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
vim.o.termguicolors = false
|
||||||
|
if not pcall(vim.cmd.colorscheme, "industry") then
|
||||||
|
pcall(vim.cmd.colorscheme, "default")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.api.nvim_create_autocmd("VimEnter", {
|
||||||
|
callback = function()
|
||||||
|
set_colorscheme()
|
||||||
|
|
||||||
|
local tty = is_linux_console()
|
||||||
|
|
||||||
|
-- LUALINE: no icons, simple separators, TTY theme
|
||||||
|
pcall(function()
|
||||||
|
local ok, lualine = pcall(require, "lualine")
|
||||||
|
if not ok then return end
|
||||||
|
if tty then
|
||||||
|
lualine.setup({
|
||||||
|
options = {
|
||||||
|
theme = "16color", -- built-in, safe for TTY
|
||||||
|
icons_enabled = false,
|
||||||
|
component_separators = "",
|
||||||
|
section_separators = "",
|
||||||
|
globalstatus = true,
|
||||||
|
},
|
||||||
|
sections = {
|
||||||
|
lualine_a = { "mode" },
|
||||||
|
lualine_b = { "branch" },
|
||||||
|
lualine_c = { { "filename", file_status = true, path = 1 } },
|
||||||
|
lualine_x = { "encoding", "fileformat", "filetype" },
|
||||||
|
lualine_y = { "progress" },
|
||||||
|
lualine_z = { "location" },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
else
|
||||||
|
lualine.setup({
|
||||||
|
options = {
|
||||||
|
theme = "tokyonight",
|
||||||
|
icons_enabled = true,
|
||||||
|
globalstatus = true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- BARBAR: kill icons in TTY, simplify separators
|
||||||
|
pcall(function()
|
||||||
|
vim.g.barbar_auto_setup = false
|
||||||
|
local ok, barbar = pcall(require, "barbar")
|
||||||
|
if not ok then return end
|
||||||
|
if tty then
|
||||||
|
barbar.setup({
|
||||||
|
animation = false,
|
||||||
|
auto_hide = false,
|
||||||
|
sidebar_filetypes = { NvimTree = true, undotree = { text = "Undotree" } },
|
||||||
|
icons = {
|
||||||
|
-- aggressively disable anything icon-like
|
||||||
|
buffer_index = false,
|
||||||
|
buffer_number = false,
|
||||||
|
button = "", -- close button
|
||||||
|
diagnostics = {
|
||||||
|
[vim.diagnostic.severity.ERROR] = { enabled = false },
|
||||||
|
[vim.diagnostic.severity.WARN] = { enabled = false },
|
||||||
|
[vim.diagnostic.severity.INFO] = { enabled = false },
|
||||||
|
[vim.diagnostic.severity.HINT] = { enabled = false },
|
||||||
|
},
|
||||||
|
gitsigns = { added = {enabled=false}, changed = {enabled=false}, deleted = {enabled=false} },
|
||||||
|
filetype = { enabled = false },
|
||||||
|
pinned = { button = "", filename = true },
|
||||||
|
modified = { button = "*" }, -- simple ASCII marker
|
||||||
|
separator = { left = "|", right = "|" },
|
||||||
|
inactive = { separator = { left = "", right = "" } },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
else
|
||||||
|
barbar.setup({}) -- your normal config, or keep defaults
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- If you use web-devicons, disable it in TTY to avoid glyphs
|
||||||
|
if is_linux_console() then
|
||||||
|
-- If using lazy.nvim, better to conditionally load the plugin (see spec below).
|
||||||
|
if package.loaded["nvim-web-devicons"] then
|
||||||
|
local ok, devicons = pcall(require, "nvim-web-devicons")
|
||||||
|
if ok and devicons.has_loaded() then
|
||||||
|
-- there's no runtime "disable", but not using it in barbar/lualine is enough.
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
3
home/config/nvim/lazy-lock.json
Normal file
3
home/config/nvim/lazy-lock.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
9
home/config/nvim/lua/autocmds.lua
Normal file
9
home/config/nvim/lua/autocmds.lua
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
local vim = vim
|
||||||
|
|
||||||
|
vim.api.nvim_create_autocmd({ "BufEnter", "BufWritePost" }, {
|
||||||
|
group = vim.api.nvim_create_augroup("TWTask", { clear = true }),
|
||||||
|
pattern = "*.wiki", -- Pattern to match Markdown files
|
||||||
|
callback = function()
|
||||||
|
vim.cmd('TWSyncTasks')
|
||||||
|
end,
|
||||||
|
})
|
||||||
112
home/config/nvim/lua/completion.lua
Normal file
112
home/config/nvim/lua/completion.lua
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
local cmp = require("cmp")
|
||||||
|
|
||||||
|
cmp.setup({
|
||||||
|
snippet = {
|
||||||
|
expand = function(args)
|
||||||
|
require('luasnip').lsp_expand(args.body) -- For `luasnip` users.
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
window = {
|
||||||
|
completion = cmp.config.window.bordered(),
|
||||||
|
documentation = cmp.config.window.bordered(),
|
||||||
|
},
|
||||||
|
mapping = cmp.mapping.preset.insert({
|
||||||
|
["<C-b>"] = cmp.mapping.scroll_docs(-4),
|
||||||
|
["<C-f>"] = cmp.mapping.scroll_docs(4),
|
||||||
|
["<C-Space>"] = cmp.mapping.complete(),
|
||||||
|
["<C-e>"] = cmp.mapping.abort(),
|
||||||
|
["<CR>"] = cmp.mapping.confirm({ select = false }), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items.
|
||||||
|
["<C-Tab>"] = cmp.mapping(function(fallback)
|
||||||
|
if cmp.visible() then
|
||||||
|
cmp.select_next_item()
|
||||||
|
else
|
||||||
|
fallback()
|
||||||
|
end
|
||||||
|
end, { "i", "s" }),
|
||||||
|
|
||||||
|
["<S-Tab>"] = cmp.mapping(function(fallback)
|
||||||
|
if cmp.visible() then
|
||||||
|
cmp.select_prev_item()
|
||||||
|
else
|
||||||
|
fallback()
|
||||||
|
end
|
||||||
|
end, { "i", "s" }),
|
||||||
|
}),
|
||||||
|
sources = cmp.config.sources({
|
||||||
|
{ name = "nvim_lua" },
|
||||||
|
{ name = "copilot", group_index = 3 },
|
||||||
|
{ name = "nvim_lsp", group_index = 1 },
|
||||||
|
{ name = "path", group_index = 3 },
|
||||||
|
{ name = "luasnip", group_index = 2 },
|
||||||
|
{ name = "buffer" },
|
||||||
|
{ name = "calc" },
|
||||||
|
{ name = 'orgmode' },
|
||||||
|
-- { name = 'vsnip' }, -- For vsnip users.
|
||||||
|
-- { name = 'luasnip' }, -- For luasnip users.
|
||||||
|
-- { name = 'ultisnips' }, -- For ultisnips users.
|
||||||
|
-- { name = 'snippy' }, -- For snippy users.
|
||||||
|
{ name = "crates" },
|
||||||
|
-- { name = 'cmdline' },
|
||||||
|
-- { name = 'neorg' },
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Set configuration for specific filetype.
|
||||||
|
cmp.setup.filetype("gitcommit", {
|
||||||
|
sources = cmp.config.sources({
|
||||||
|
{ name = "cmp_git" }, -- You can specify the `cmp_git` source if you were installed it.
|
||||||
|
}, {
|
||||||
|
{ name = "buffer" },
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Use buffer source for `/` and `?` (if you enabled `native_menu`, this won't work anymore).
|
||||||
|
cmp.setup.cmdline({ "/", "?" }, {
|
||||||
|
mapping = cmp.mapping.preset.cmdline(),
|
||||||
|
sources = {
|
||||||
|
{ name = "buffer" },
|
||||||
|
{ name = "cmdline" },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Use cmdline & path source for ':' (if you enabled `native_menu`, this won't work anymore).
|
||||||
|
cmp.setup.cmdline(":", {
|
||||||
|
mapping = cmp.mapping.preset.cmdline(),
|
||||||
|
sources = cmp.config.sources({
|
||||||
|
{ name = "path" },
|
||||||
|
}, {
|
||||||
|
{ name = "cmdline" },
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Set up lspconfig.
|
||||||
|
-- require("cmp_nvim_lsp").default_capabilities()
|
||||||
|
local capabilities = require("cmp_nvim_lsp").default_capabilities()
|
||||||
|
-- Replace <YOUR_LSP_SERVER> with each lsp server you've enabled.
|
||||||
|
-- require('lspconfig')['<YOUR_LSP_SERVER>'].setup {
|
||||||
|
-- capabilities = capabilities
|
||||||
|
-- }
|
||||||
|
require("lspconfig").clangd.setup({
|
||||||
|
capabilities = capabilities,
|
||||||
|
})
|
||||||
|
require("lspconfig").taplo.setup({
|
||||||
|
capabilities = capabilities,
|
||||||
|
})
|
||||||
|
require("lspconfig").marksman.setup({
|
||||||
|
capabilities = capabilities,
|
||||||
|
})
|
||||||
|
require("lspconfig").lua_ls.setup({
|
||||||
|
capabilities = capabilities,
|
||||||
|
})
|
||||||
|
require("lspconfig").rust_analyzer.setup({
|
||||||
|
capabilities = capabilities,
|
||||||
|
})
|
||||||
|
require("lspconfig").zls.setup({
|
||||||
|
capabilities = capabilities,
|
||||||
|
})
|
||||||
|
require("lspconfig").pyright.setup({
|
||||||
|
capabilities = capabilities,
|
||||||
|
})
|
||||||
|
-- require'lspconfig'.jedi_language_server.setup {
|
||||||
|
-- capabilities = capabilities,
|
||||||
|
-- }
|
||||||
60
home/config/nvim/lua/diagnostics.lua
Normal file
60
home/config/nvim/lua/diagnostics.lua
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
require("tiny-inline-diagnostic").setup({
|
||||||
|
-- Style preset for diagnostic messages
|
||||||
|
-- Available options:
|
||||||
|
-- "modern", "classic", "minimal", "powerline",
|
||||||
|
-- "ghost", "simple", "nonerdfont", "amongus"
|
||||||
|
preset = "modern",
|
||||||
|
transparent_bg = false, -- Set the background of the diagnostic to transparent
|
||||||
|
transparent_cursorline = false, -- Set the background of the cursorline to transparent (only one the first diagnostic)
|
||||||
|
hi = {
|
||||||
|
error = "DiagnosticError", -- Highlight group for error messages
|
||||||
|
warn = "DiagnosticWarn", -- Highlight group for warning messages
|
||||||
|
info = "DiagnosticInfo", -- Highlight group for informational messages
|
||||||
|
hint = "DiagnosticHint", -- Highlight group for hint or suggestion messages
|
||||||
|
arrow = "NonText", -- Highlight group for diagnostic arrows
|
||||||
|
background = "CursorLine",
|
||||||
|
mixing_color = "None",
|
||||||
|
},
|
||||||
|
|
||||||
|
options = {
|
||||||
|
show_source = {
|
||||||
|
enabled = false,
|
||||||
|
if_many = false,
|
||||||
|
},
|
||||||
|
use_icons_from_diagnostic = false,
|
||||||
|
set_arrow_to_diag_color = false,
|
||||||
|
add_messages = true,
|
||||||
|
throttle = 20,
|
||||||
|
softwrap = 30,
|
||||||
|
multilines = {
|
||||||
|
enabled = false,
|
||||||
|
always_show = false,
|
||||||
|
trim_whitespaces = false,
|
||||||
|
tabstop = 4,
|
||||||
|
},
|
||||||
|
show_all_diags_on_cursorline = false,
|
||||||
|
enable_on_insert = false,
|
||||||
|
enable_on_select = false,
|
||||||
|
|
||||||
|
overflow = {
|
||||||
|
mode = "wrap",
|
||||||
|
padding = 0,
|
||||||
|
},
|
||||||
|
break_line = {
|
||||||
|
enabled = false,
|
||||||
|
after = 30,
|
||||||
|
},
|
||||||
|
format = nil,
|
||||||
|
virt_texts = {
|
||||||
|
priority = 2048,
|
||||||
|
},
|
||||||
|
severity = {
|
||||||
|
vim.diagnostic.severity.ERROR,
|
||||||
|
vim.diagnostic.severity.WARN,
|
||||||
|
vim.diagnostic.severity.INFO,
|
||||||
|
vim.diagnostic.severity.HINT,
|
||||||
|
},
|
||||||
|
overwrite_events = nil,
|
||||||
|
},
|
||||||
|
disabled_ft = {} -- List of filetypes to disable the plugin
|
||||||
|
})
|
||||||
166
home/config/nvim/lua/functions.lua
Normal file
166
home/config/nvim/lua/functions.lua
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
local vim = vim
|
||||||
|
local fzflua = require("fzf-lua")
|
||||||
|
local Job = require'plenary.job'
|
||||||
|
|
||||||
|
function t3_find_file()
|
||||||
|
-- local file_name = vim.fn.input("Find File: ", "", "file")
|
||||||
|
fzflua.files()
|
||||||
|
end
|
||||||
|
|
||||||
|
function t3_recent_files()
|
||||||
|
fzflua.oldfiles()
|
||||||
|
end
|
||||||
|
|
||||||
|
function t3_org_files()
|
||||||
|
fzflua.files({ cwd = '~/org/'})
|
||||||
|
end
|
||||||
|
|
||||||
|
function t3_project_files()
|
||||||
|
fzflua.files({ cwd = '~/Projects/'})
|
||||||
|
end
|
||||||
|
|
||||||
|
function t3_dot_files()
|
||||||
|
fzflua.files({ cwd = '~/.dotfiles/'})
|
||||||
|
end
|
||||||
|
|
||||||
|
function t3_config_files()
|
||||||
|
fzflua.files({ cwd = '~/.dotfiles/'})
|
||||||
|
end
|
||||||
|
|
||||||
|
function t3_snip_capture(name)
|
||||||
|
if type(name) ~= "string" or name == "" then
|
||||||
|
print("Error: Invalid snippet name")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
-- local timestamp = os.date("%Y%m%d%H%M%S")
|
||||||
|
local snippet_path = "~/.config/nvim/snippets/"
|
||||||
|
local filename = snippet_path .. name:gsub("%s+", "_") .. ".lua"
|
||||||
|
local file = io.open(vim.fn.expand(filename), "w")
|
||||||
|
if file == nil then
|
||||||
|
print("Error: Could not open file for editing.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local previous_buffer = vim.api.nvim_get_current_buf()
|
||||||
|
file:write("local ls = require('luasnip')\n\nls.add_snippets(\"{}\", {\n\tls.parser.parse_snippet(\n\t\t'{}',\n\t\t'{}'),\n})")
|
||||||
|
file:close()
|
||||||
|
vim.cmd("e " .. filename)
|
||||||
|
vim.bo.filetype = 'lua'
|
||||||
|
-- vim.cmd("Neorg inject-metadata")
|
||||||
|
-- Set an autocmd to return to the previous buffer when the note buffer is closed
|
||||||
|
vim.api.nvim_create_autocmd("BufLeave", {
|
||||||
|
buffer = 0, -- Current buffer (the note buffer)
|
||||||
|
callback = function()
|
||||||
|
load_snippets_from_directory(snippet_path)
|
||||||
|
vim.cmd("buffer " .. previous_buffer)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
print("Captured snippet: " .. filename)
|
||||||
|
end
|
||||||
|
|
||||||
|
function t3_org_capture(name)
|
||||||
|
if type(name) ~= "string" or name == "" then
|
||||||
|
print("Error: Invalid note name")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local timestamp = os.date("%Y%m%d%H%M%S")
|
||||||
|
local org_path = "~/org/.org-roam/"
|
||||||
|
local filename = org_path .. timestamp .. "-" .. name:gsub("%s+", "_") .. ".norg"
|
||||||
|
local file = io.open(vim.fn.expand(filename), "w")
|
||||||
|
if file == nil then
|
||||||
|
print("Error: Could not open file for editing.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local previous_buffer = vim.api.nvim_get_current_buf()
|
||||||
|
file:write("* " .. name .. "\n\n")
|
||||||
|
file:close()
|
||||||
|
vim.cmd("e " .. filename)
|
||||||
|
vim.bo.filetype = 'norg'
|
||||||
|
vim.cmd("Neorg inject-metadata")
|
||||||
|
-- Set an autocmd to return to the previous buffer when the note buffer is closed
|
||||||
|
vim.api.nvim_create_autocmd("BufLeave", {
|
||||||
|
buffer = 0, -- Current buffer (the note buffer)
|
||||||
|
callback = function()
|
||||||
|
vim.cmd("buffer " .. previous_buffer)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
print("Captured note: " .. filename)
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.api.nvim_create_user_command(
|
||||||
|
'NeorgCapture',
|
||||||
|
function()
|
||||||
|
-- local title = vim.fn.input("Title: ")
|
||||||
|
local current_workspace = vim.g.neorg_workspace_name
|
||||||
|
if not current_workspace then
|
||||||
|
vim.cmd("Neorg workspace default")
|
||||||
|
end
|
||||||
|
vim.ui.input({ prompt = "Enter note name: "}, function(note_name)
|
||||||
|
if not note_name or note_name == "" then
|
||||||
|
print("Error: Note name required!")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
t3_org_capture(note_name)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end,
|
||||||
|
{ nargs = 0, desc = "Capture a Neorg note" }
|
||||||
|
)
|
||||||
|
|
||||||
|
vim.api.nvim_create_user_command(
|
||||||
|
'CaptureSnip',
|
||||||
|
function()
|
||||||
|
-- local title = vim.fn.input("Title: ")
|
||||||
|
-- local current_workspace = vim.g.neorg_workspace_name
|
||||||
|
-- if not current_workspace then
|
||||||
|
-- vim.cmd("Neorg workspace default")
|
||||||
|
-- end
|
||||||
|
vim.ui.input({ prompt = "Enter snippet name: "}, function(snip_name)
|
||||||
|
if not snip_name or snip_name == "" then
|
||||||
|
print("Error: Snippet name required!")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
t3_snip_capture(snip_name)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end,
|
||||||
|
{ nargs = 0, desc = "Capture a Neorg note" }
|
||||||
|
)
|
||||||
|
function t3_buffers()
|
||||||
|
fzflua.buffers()
|
||||||
|
end
|
||||||
|
|
||||||
|
function t3_tabs()
|
||||||
|
fzflua.tabs()
|
||||||
|
end
|
||||||
|
|
||||||
|
function t3_live_grep(state)
|
||||||
|
state = state or 0
|
||||||
|
if state == 0 then
|
||||||
|
fzflua.live_grep()
|
||||||
|
else
|
||||||
|
fzflua.live_grep_resume()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function t3_grep(state)
|
||||||
|
state = state or 0
|
||||||
|
if state == 0 then
|
||||||
|
fzflua.grep_project()
|
||||||
|
else
|
||||||
|
fzflua.grep()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function t3_make_ctags()
|
||||||
|
Job:new({
|
||||||
|
command = 'ctags',
|
||||||
|
args = { '-R .' },
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.api.nvim_create_autocmd("FileType", {
|
||||||
|
pattern = { "markdown", "norg", "md", "wiki" }, -- Set for markdown file type
|
||||||
|
callback = function()
|
||||||
|
vim.api.nvim_buf_set_keymap(0, "n", "<C-i>", "o* [ ] ", { noremap = true, silent = true })
|
||||||
|
vim.api.nvim_buf_set_keymap(0, "i", "<C-i>", "<Esc>0wi* [ ] ", { noremap = true, silent = true })
|
||||||
|
end,
|
||||||
|
})
|
||||||
85
home/config/nvim/lua/keymaps.lua
Normal file
85
home/config/nvim/lua/keymaps.lua
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
local vim = vim
|
||||||
|
|
||||||
|
vim.keymap.set("n", "<C-w>s", function()
|
||||||
|
vim.cmd("split")
|
||||||
|
vim.cmd("wincmd j")
|
||||||
|
end, { noremap = true })
|
||||||
|
|
||||||
|
vim.keymap.set("n", "<C-w>v", function()
|
||||||
|
vim.cmd("vsplit")
|
||||||
|
vim.cmd("wincmd l")
|
||||||
|
end, { noremap = true })
|
||||||
|
|
||||||
|
-- Leader Maps
|
||||||
|
vim.keymap.set("n", "<leader>f", "", { desc = "Files"})
|
||||||
|
vim.keymap.set("n", "<leader>ff", ":FzfLua files<CR>", { desc = "File Finder"})
|
||||||
|
-- vim.keymap.set("n", "<leader>fe", ":Pick files<CR>", { desc = "File Picker"})
|
||||||
|
vim.keymap.set("n", "<leader>ft", t3_toggle_netrw, { desc = "File Tree"})
|
||||||
|
|
||||||
|
vim.keymap.set("n", "<leader>b", "", { desc = "Buffers"})
|
||||||
|
vim.keymap.set("n", "<leader>bb", ":Pick buffers<CR>", { desc = "Buffer Picker"})
|
||||||
|
vim.keymap.set("n", "<leader>bp", ":bp<CR>", { desc = "Previous"})
|
||||||
|
vim.keymap.set("n", "<leader>bn", ":bn<CR>", { desc = "Next"})
|
||||||
|
vim.keymap.set("n", "<leader>bd", ":bd<CR>", { desc = "Delete"})
|
||||||
|
|
||||||
|
vim.keymap.set("n", "<leader>G", "", { desc = "Grep"})
|
||||||
|
vim.keymap.set("n", "<leader>Gg", ":FzfLua grep<CR>", { desc = "Grep"})
|
||||||
|
vim.keymap.set("n", "<leader>Gr", ":FzfLua grep resume=true<CR>", { desc = "Resume Grep"})
|
||||||
|
|
||||||
|
vim.keymap.set("n", "<leader>g", "", { desc = "Git"})
|
||||||
|
vim.keymap.set("n", "<leader>gg", ":LazyGit<CR>", { desc = "LazyGit"})
|
||||||
|
vim.keymap.set("n", "<leader>gC", ":LazyGitConfig<CR>", { desc = "LazyGit Config"})
|
||||||
|
vim.keymap.set("n", "<leader>gc", ":LazyGitFilter<CR>", { desc = "Commits"})
|
||||||
|
vim.keymap.set("n", "<leader>gl", ":LazyGitLog<CR>", { desc = "Log"})
|
||||||
|
|
||||||
|
vim.keymap.set("n", "<leader><Tab>", "", { desc = "Tabs"})
|
||||||
|
vim.keymap.set("n", "<leader><Tab><Tab>", ":tabnew<CR>", { desc = "New Tab"})
|
||||||
|
vim.keymap.set("n", "<leader><Tab>p", ":tabprevious<CR>", { desc = "Previous Tab"})
|
||||||
|
vim.keymap.set("n", "<leader><Tab>n", ":tabnext<CR>", { desc = "Next Tab"})
|
||||||
|
vim.keymap.set("n", "<leader><Tab>d", ":tabclose<CR>", { desc = "Delete Tab"})
|
||||||
|
vim.keymap.set("n", "<leader><Tab>l", ":tablast<CR>", { desc = "Last Tab"})
|
||||||
|
vim.keymap.set("n", "<leader><Tab>f", ":tabfirst<CR>", { desc = "First Tab"})
|
||||||
|
vim.keymap.set("n", "<leader><Tab>m", ":tabmove<CR>", { desc = "Move Tab"})
|
||||||
|
vim.keymap.set("n", "<leader><Tab>r", ":tabrenumber<CR>", { desc = "Renumber Tabs"})
|
||||||
|
vim.keymap.set("n", "<leader><Tab>c", ":tabclose!<CR>", { desc = "Force Close Tab"})
|
||||||
|
|
||||||
|
vim.keymap.set("n", "gR", "<CMD>Glance references<CR>", { desc = "Glance References" })
|
||||||
|
vim.keymap.set("n", "gD", "<CMD>Glance definitions<CR>", { desc = "Glance Definitions" })
|
||||||
|
vim.keymap.set("n", "gY", "<CMD>Glance type_definitions<CR>", { desc = "Glance Type Definitions" })
|
||||||
|
vim.keymap.set("n", "gM", "<CMD>Glance implementations<CR>", { desc = "Glance Implementations" })
|
||||||
|
|
||||||
|
vim.keymap.set("n", "<A-Tab>", ":b#<CR>", { desc = "Switch to Last Buffer" })
|
||||||
|
vim.keymap.set("n", "<A-Left>", ":bprevious<CR>", { desc = "Previous Buffer" })
|
||||||
|
vim.keymap.set("n", "<A-Right>", ":bnext<CR>", { desc = "Next Buffer" })
|
||||||
|
vim.keymap.set("n", "<A-Up>", ":tabprevious<CR>", { desc = "Previous Tab" })
|
||||||
|
vim.keymap.set("n", "<A-Down>", ":tabnext<CR>", { desc = "Next Tab" })
|
||||||
|
vim.keymap.set("n", "<A-1>", "<Cmd>BufferGoto 1<CR>", { desc = "Go to Buffer 1" })
|
||||||
|
vim.keymap.set("n", "<A-2>", "<Cmd>BufferGoto 2<CR>", { desc = "Go to Buffer 2" })
|
||||||
|
vim.keymap.set("n", "<A-3>", "<Cmd>BufferGoto 3<CR>", { desc = "Go to Buffer 3" })
|
||||||
|
vim.keymap.set("n", "<A-4>", "<Cmd>BufferGoto 4<CR>", { desc = "Go to Buffer 4" })
|
||||||
|
vim.keymap.set("n", "<A-5>", "<Cmd>BufferGoto 5<CR>", { desc = "Go to Buffer 5" })
|
||||||
|
vim.keymap.set("n", "<A-6>", "<Cmd>BufferGoto 6<CR>", { desc = "Go to Buffer 6" })
|
||||||
|
vim.keymap.set("n", "<A-7>", "<Cmd>BufferGoto 7<CR>", { desc = "Go to Buffer 7" })
|
||||||
|
vim.keymap.set("n", "<A-8>", "<Cmd>BufferGoto 8<CR>", { desc = "Go to Buffer 8" })
|
||||||
|
vim.keymap.set("n", "<A-9>", "<Cmd>BufferGoto 9<CR>", { desc = "Go to Buffer 9" })
|
||||||
|
vim.keymap.set("n", "<A-0>", "<Cmd>BufferLast<CR>", { desc = "Go to Last Buffer" })
|
||||||
|
|
||||||
|
|
||||||
|
-- CTRL X Maps
|
||||||
|
vim.keymap.set("n", "<C-x><C-b>", ":Pick buffers<CR>", { desc = "Buffer Picker"})
|
||||||
|
vim.keymap.set("n", "<C-x><C-f>", ":Pick files<CR>", { desc = "File Picker"})
|
||||||
|
vim.keymap.set("n", "<C-x><C-h>", ":Pick help<CR>", { desc = "Help Picker"})
|
||||||
|
vim.keymap.set("n", "<C-x><C-g>", "", { desc = "Grep"})
|
||||||
|
vim.keymap.set("n", "<C-x><C-g>g", ":Pick grep<CR>", { desc = "Grep"})
|
||||||
|
vim.keymap.set("n", "<C-x><C-g>l", ":Pick grep_live<CR>", { desc = "Live Grep"})
|
||||||
|
vim.keymap.set("v", "<C-x><C-c>", ":'<,'>SnipRun<CR>", { silent = true, desc = "Run Selection" })
|
||||||
|
vim.keymap.set("n", "<C-x><C-c>", ":<Plug>SnipRun<CR>", { desc = "Run Current Line" })
|
||||||
|
vim.keymap.set("n", "<C-x><C-b>", ":%SnipRun<CR>", { desc = "Run Buffer" })
|
||||||
|
vim.keymap.set("n", "<C-x><C-k>", "<Plug>SnipReset<CR>", { desc = "Run Buffer" })
|
||||||
|
vim.keymap.set("n", "<C-x><C-n>", "", { desc = "Notes"})
|
||||||
|
vim.keymap.set("n", "<C-x><C-n>e", "<cmd>TWEditTask<cr>", { desc = "TaskWarrior Edit", noremap = true, silent = true })
|
||||||
|
vim.keymap.set("n", "<C-x><C-n>v", "<cmd>TWView<cr>", { desc = "View Tasks", noremap = true, silent = true })
|
||||||
|
vim.keymap.set("n", "<C-x><C-n>u", "<cmd>TWUpdateCurrent<cr>", { desc="Update Tasks", noremap = true, silent = true })
|
||||||
|
vim.keymap.set("n", "<C-x><C-n>s", "<cmd>TWSyncTasks<cr>", { desc = "Sync Tasks", noremap = true, silent = true })
|
||||||
|
vim.keymap.set("n", "<C-x><C-n><c-space>", "<cmd>TWToggle<cr>", { desc = "Toggle Taskwarrior", silent = true })
|
||||||
|
|
||||||
57
home/config/nvim/lua/lsp.lua
Normal file
57
home/config/nvim/lua/lsp.lua
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
local vim = vim
|
||||||
|
-- vim.cmd [[
|
||||||
|
-- augroup LspCompletion
|
||||||
|
-- autocmd!
|
||||||
|
-- autocmd InsertEnter * setlocal omnifunc=v:lua.vim.lsp.omnifunc
|
||||||
|
-- autocmd TextChangedI * if pumvisible() == 0 | silent! lua vim.fn.complete(vim.fn.col('.'), vim.fn["vim.lsp.omnifunc"]()) | endif
|
||||||
|
-- augroup END
|
||||||
|
-- ]]
|
||||||
|
vim.lsp.enable('lua_ls')
|
||||||
|
vim.lsp.enable('gopls', {
|
||||||
|
settings = {
|
||||||
|
gopls = {
|
||||||
|
analyses = {
|
||||||
|
unusedparams = true,
|
||||||
|
unusedwrite = true,
|
||||||
|
shadow = true,
|
||||||
|
},
|
||||||
|
staticcheck = true,
|
||||||
|
usePlaceholders = true,
|
||||||
|
hints = {
|
||||||
|
assignVariableTypes = true,
|
||||||
|
compositeLiteralFields = true,
|
||||||
|
compositeLiteralTypes = true,
|
||||||
|
functionTypeParameters = true,
|
||||||
|
parameterNames = true,
|
||||||
|
rangeVariableTypes = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
require("lsp_signature").setup({
|
||||||
|
debug = false,
|
||||||
|
bind = true, -- registers signature handler
|
||||||
|
doc_lines = 10,
|
||||||
|
max_height = 12,
|
||||||
|
max_width = function() return math.floor(vim.api.nvim_win_get_width(0) * 0.8) end,
|
||||||
|
wrap = true,
|
||||||
|
floating_window = true, -- show the popup
|
||||||
|
floating_window_above_cur_line = true,
|
||||||
|
floating_window_off_x = 1,
|
||||||
|
floating_window_off_y = 0,
|
||||||
|
|
||||||
|
-- IMPORTANT: don’t inline (you can change later if you want)
|
||||||
|
hint_enable = true,
|
||||||
|
hint_inline = function() return false end,
|
||||||
|
|
||||||
|
hint_prefix = "🐼 ",
|
||||||
|
hint_scheme = "String",
|
||||||
|
hi_parameter = "LspSignatureActiveParameter",
|
||||||
|
handler_opts = { border = "rounded" },
|
||||||
|
|
||||||
|
always_trigger = false,
|
||||||
|
extra_trigger_chars = { "(", "," }, -- good default
|
||||||
|
zindex = 200,
|
||||||
|
padding = "",
|
||||||
|
timer_interval = 200,
|
||||||
|
})
|
||||||
55
home/config/nvim/lua/options.lua
Normal file
55
home/config/nvim/lua/options.lua
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
local vim = vim
|
||||||
|
|
||||||
|
vim.o.number = true
|
||||||
|
vim.o.relativenumber = true
|
||||||
|
vim.o.tabstop = 2
|
||||||
|
vim.o.shiftwidth = 2
|
||||||
|
vim.o.wrap = false
|
||||||
|
vim.o.scrolloff = 5
|
||||||
|
vim.o.colorcolumn = "80"
|
||||||
|
vim.o.wildmenu = true
|
||||||
|
vim.o.wildmode = "longest:full,full"
|
||||||
|
vim.o.wildoptions = "pum"
|
||||||
|
vim.g.mapleader = " "
|
||||||
|
vim.o.termguicolors = true
|
||||||
|
vim.o.winborder = "double"
|
||||||
|
vim.o.clipboard = "unnamedplus"
|
||||||
|
vim.o.completeopt = "menuone"
|
||||||
|
-- vim.o.completeopt = "menuone,noinsert,noselect"
|
||||||
|
vim.o.cursorline = true
|
||||||
|
|
||||||
|
vim.g.netrw_keepdir = 1
|
||||||
|
vim.g.netrw_winsize = 15
|
||||||
|
vim.g.netrw_banner = 0
|
||||||
|
vim.g.netrw_localcopydircmd = 'cp -avr'
|
||||||
|
vim.g.netrw_liststyle = 3
|
||||||
|
vim.g.netrw_browse_split = 4
|
||||||
|
|
||||||
|
vim.o.foldmethod = "expr"
|
||||||
|
vim.o.foldexpr = "nvim_treesitter#foldexpr()"
|
||||||
|
vim.o.foldlevel = 1
|
||||||
|
vim.o.foldenable = true
|
||||||
|
|
||||||
|
vim.o.undofile = true
|
||||||
|
vim.o.undodir = vim.fn.stdpath("data") .. "/undo"
|
||||||
|
|
||||||
|
vim.api.nvim_create_autocmd("FileType", {
|
||||||
|
pattern = "help",
|
||||||
|
callback = function()
|
||||||
|
vim.opt_local.wrap = true
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
vim.api.nvim_create_autocmd("FileType", {
|
||||||
|
pattern = "markdown",
|
||||||
|
callback = function()
|
||||||
|
vim.opt_local.wrap = true
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
vim.api.nvim_create_autocmd("BufWritePost", {
|
||||||
|
pattern = ".wiki",
|
||||||
|
callback = function()
|
||||||
|
vim.cmd("VimwikiGenerateLinks")
|
||||||
|
end,
|
||||||
|
})
|
||||||
114
home/config/nvim/lua/plugins.lua
Normal file
114
home/config/nvim/lua/plugins.lua
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
local vim = vim
|
||||||
|
vim.pack.add({
|
||||||
|
{ src = "https://github.com/folke/tokyonight.nvim" },
|
||||||
|
{ src = "https://github.com/nvim-tree/nvim-web-devicons" },
|
||||||
|
{ src = "https://github.com/ibhagwan/fzf-lua" },
|
||||||
|
{ src = "https://github.com/echasnovski/mini.pick" },
|
||||||
|
{ src = "https://github.com/echasnovski/mini.icons" },
|
||||||
|
{ src = "https://github.com/echasnovski/mini.files" },
|
||||||
|
{ src = "https://github.com/echasnovski/mini.pairs" },
|
||||||
|
{ src = "https://github.com/echasnovski/mini.notify" },
|
||||||
|
{ src = "https://github.com/echasnovski/mini.surround" },
|
||||||
|
{ src = "https://github.com/echasnovski/mini.indentscope" },
|
||||||
|
{ src = "https://github.com/echasnovski/mini.fuzzy" },
|
||||||
|
{ src = "https://github.com/echasnovski/mini.tabline" },
|
||||||
|
{ src = "https://github.com/nvim-lualine/lualine.nvim" },
|
||||||
|
{ src = "https://github.com/folke/which-key.nvim" },
|
||||||
|
{ src = "https://github.com/L3MON4D3/LuaSnip" },
|
||||||
|
{ src = "https://github.com/neovim/nvim-lspconfig" },
|
||||||
|
{ src = "https://github.com/hrsh7th/nvim-cmp" },
|
||||||
|
{ src = "https://github.com/hrsh7th/cmp-nvim-lsp" },
|
||||||
|
{ src = "https://github.com/hrsh7th/cmp-buffer" },
|
||||||
|
{ src = "https://github.com/hrsh7th/cmp-path" },
|
||||||
|
{ src = "https://github.com/hrsh7th/cmp-cmdline" },
|
||||||
|
{ src = "https://github.com/hrsh7th/cmp-nvim-lua" },
|
||||||
|
{ src = "https://github.com/saadparwaiz1/cmp_luasnip" },
|
||||||
|
{ src = "https://github.com/github/copilot.vim" },
|
||||||
|
{ src = "https://github.com/pysan3/pathlib.nvim" },
|
||||||
|
-- { src = "https://github.com/nvim-orgmode/orgmode" },
|
||||||
|
-- { src = "https://github.com/chipsenkbeil/org-roam.nvim" },
|
||||||
|
-- { src = "https://github.com/danilshvalov/org-modern.nvim" },
|
||||||
|
{ src = "https://github.com/nvim-orgmode/org-bullets.nvim" },
|
||||||
|
{ src = "https://github.com/lukas-reineke/headlines.nvim" },
|
||||||
|
{ src = "https://github.com/michaelb/sniprun", run = "bash install.sh 1" },
|
||||||
|
{ src = "https://github.com/akinsho/toggleterm.nvim" },
|
||||||
|
{ src = "https://github.com/kdheepak/lazygit.nvim" },
|
||||||
|
{ src = "https://github.com/saecki/crates.nvim" },
|
||||||
|
{ src = "https://github.com/nvim-treesitter/nvim-treesitter" },
|
||||||
|
{ src = "https://github.com/folke/trouble.nvim" },
|
||||||
|
{ src = "https://github.com/folke/todo-comments.nvim" },
|
||||||
|
{ src = "https://github.com/MunifTanjim/nui.nvim" },
|
||||||
|
{ src = "https://github.com/huantrinh1802/m_taskwarrior_d.nvim" },
|
||||||
|
{ src = "https://github.com/rmagatti/auto-session" },
|
||||||
|
{ src = "https://github.com/romgrk/barbar.nvim" },
|
||||||
|
{ src = "https://github.com/christoomey/vim-tmux-navigator" },
|
||||||
|
{ src = "https://github.com/rachartier/tiny-inline-diagnostic.nvim" },
|
||||||
|
{ src = "https://github.com/zeioth/garbage-day.nvim" },
|
||||||
|
{ src = "https://github.com/ray-x/lsp_signature.nvim" },
|
||||||
|
{ src = "https://github.com/DNLHC/glance.nvim" },
|
||||||
|
{ src = "https://github.com/rmagatti/logger.nvim" },
|
||||||
|
{ src = "https://github.com/rmagatti/goto-preview" },
|
||||||
|
})
|
||||||
|
|
||||||
|
require('mini.icons').setup({})
|
||||||
|
require('mini.pick').setup({})
|
||||||
|
require('mini.pairs').setup({})
|
||||||
|
require('mini.notify').setup({})
|
||||||
|
require('mini.surround').setup({})
|
||||||
|
require('mini.indentscope').setup({})
|
||||||
|
require('mini.tabline').setup({})
|
||||||
|
require('mini.fuzzy').setup({})
|
||||||
|
require('lualine').setup({ options = { theme = 'tokyonight' } })
|
||||||
|
require('which-key').setup({})
|
||||||
|
require('fzf-lua').setup({})
|
||||||
|
require('crates').setup({})
|
||||||
|
require('todo-comments').setup({
|
||||||
|
options = {
|
||||||
|
keywords = {
|
||||||
|
FIX = {
|
||||||
|
icon = " ", -- icon used for the sign, and in search results
|
||||||
|
color = "error", -- can be a hex color, or a named color (see below)
|
||||||
|
alt = { "FIXME", "BUG", "FIXIT", "ISSUE" }, -- a set of other keywords that all map to this FIX keywords
|
||||||
|
-- signs = false, -- configure signs for some keywords individually
|
||||||
|
},
|
||||||
|
TODO = { icon = " ", color = "info" },
|
||||||
|
HACK = { icon = " ", color = "warning" },
|
||||||
|
WARN = { icon = " ", color = "warning", alt = { "WARNING", "XXX" } },
|
||||||
|
PERF = { icon = " ", alt = { "OPTIM", "PERFORMANCE", "OPTIMIZE" } },
|
||||||
|
NOTE = { icon = " ", color = "hint", alt = { "INFO" } },
|
||||||
|
TEST = { icon = "⏲ ", color = "test", alt = { "TESTING", "PASSED", "FAILED" } },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
require('trouble').setup({})
|
||||||
|
-- require('orgmode').setup({
|
||||||
|
-- org_agenda_files = { '~/org/*' },
|
||||||
|
-- org_default_notes_file = '~/org/notes.org',
|
||||||
|
-- })
|
||||||
|
-- require('org-roam').setup({ directory = '~/org/roam' })
|
||||||
|
-- require("orgmode").setup({})
|
||||||
|
require('org-bullets').setup({})
|
||||||
|
require('headlines').setup({})
|
||||||
|
require('sniprun').setup({
|
||||||
|
binary_path = '/home/th3r00t/.local/share/nvim/site/pack/core/opt/sniprun/\
|
||||||
|
target/release/sniprun'
|
||||||
|
})
|
||||||
|
require('toggleterm').setup({
|
||||||
|
size = 20,
|
||||||
|
open_mapping = [[<c-\>]],
|
||||||
|
hide_numbers = true,
|
||||||
|
shade_filetypes = {},
|
||||||
|
shading_factor = 2,
|
||||||
|
start_in_insert = true,
|
||||||
|
insert_mappings = true,
|
||||||
|
persist_size = true,
|
||||||
|
direction = 'horizontal',
|
||||||
|
close_on_exit = true,
|
||||||
|
shell = vim.o.shell,
|
||||||
|
})
|
||||||
|
require('m_taskwarrior_d').setup({})
|
||||||
|
require("auto-session").setup({
|
||||||
|
suppressed_dirs = { "~/Downloads", "~/Documents", "~/Projects", "~/" },
|
||||||
|
})
|
||||||
|
require('barbar').setup({})
|
||||||
|
require('goto-preview').setup({ default_mappings = true })
|
||||||
11
home/config/nvim/lua/terminal.lua
Normal file
11
home/config/nvim/lua/terminal.lua
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
function _G.set_terminal_keymaps()
|
||||||
|
local opts = { buffer = 0 }
|
||||||
|
vim.keymap.set('t', '<esc>', [[<C-\><C-n>]], opts)
|
||||||
|
vim.keymap.set('t', 'jk', [[<C-\><C-n>]], opts)
|
||||||
|
vim.keymap.set('t', '<C-h>', [[<Cmd>wincmd h<CR>]], opts)
|
||||||
|
vim.keymap.set('t', '<C-j>', [[<Cmd>wincmd j<CR>]], opts)
|
||||||
|
vim.keymap.set('t', '<C-k>', [[<Cmd>wincmd k<CR>]], opts)
|
||||||
|
vim.keymap.set('t', '<C-l>', [[<Cmd>wincmd l<CR>]], opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.cmd('autocmd! TermOpen term://* lua set_terminal_keymaps()')
|
||||||
11
home/config/nvim/lua/treesitter.lua
Normal file
11
home/config/nvim/lua/treesitter.lua
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
local configs = require('nvim-treesitter.configs')
|
||||||
|
configs.setup({
|
||||||
|
ensure_installed = {
|
||||||
|
"ini", "bash", "c", "lua", "vim", "vimdoc", "query", "python",
|
||||||
|
"rust", "zig", "typescript", "svelte", "css", "html", "nix"
|
||||||
|
},
|
||||||
|
sync_install = false,
|
||||||
|
highlight = { enable = true },
|
||||||
|
indent = { enable = true, disable = { "norg" }, },
|
||||||
|
incremental_selection = { enable = true },
|
||||||
|
})
|
||||||
11
home/config/nvim/lua/utils/reload.lua
Normal file
11
home/config/nvim/lua/utils/reload.lua
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
for name,_ in pairs(package.loaded) do
|
||||||
|
if name:match("^t3")
|
||||||
|
or name:match("^options")
|
||||||
|
or name:match("^overrides")
|
||||||
|
or name:match("^plugins")
|
||||||
|
or name:match("keymaps")
|
||||||
|
or name:match("^reload")
|
||||||
|
then
|
||||||
|
package.loaded[name] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
187
home/config/nvim/lua/utils/t3_functions.lua
Normal file
187
home/config/nvim/lua/utils/t3_functions.lua
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
local vim = vim
|
||||||
|
local fzflua = require("fzf-lua")
|
||||||
|
|
||||||
|
function t3_find_file()
|
||||||
|
-- local file_name = vim.fn.input("Find File: ", "", "file")
|
||||||
|
fzflua.files()
|
||||||
|
end
|
||||||
|
|
||||||
|
function t3_recent_files()
|
||||||
|
fzflua.oldfiles()
|
||||||
|
end
|
||||||
|
|
||||||
|
function t3_org_files()
|
||||||
|
fzflua.files({ cwd = '~/org/'})
|
||||||
|
end
|
||||||
|
|
||||||
|
function t3_project_files()
|
||||||
|
fzflua.files({ cwd = '~/Projects/'})
|
||||||
|
end
|
||||||
|
|
||||||
|
function t3_dot_files()
|
||||||
|
fzflua.files({ cwd = '~/.dotfiles/'})
|
||||||
|
end
|
||||||
|
|
||||||
|
function t3_config_files()
|
||||||
|
fzflua.files({ cwd = '~/.dotfiles/'})
|
||||||
|
end
|
||||||
|
|
||||||
|
function t3_snip_capture(name)
|
||||||
|
if type(name) ~= "string" or name == "" then
|
||||||
|
print("Error: Invalid snippet name")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
-- local timestamp = os.date("%Y%m%d%H%M%S")
|
||||||
|
local snippet_path = "~/.config/nvim/snippets/"
|
||||||
|
local filename = snippet_path .. name:gsub("%s+", "_") .. ".lua"
|
||||||
|
local file = io.open(vim.fn.expand(filename), "w")
|
||||||
|
if file == nil then
|
||||||
|
print("Error: Could not open file for editing.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local previous_buffer = vim.api.nvim_get_current_buf()
|
||||||
|
file:write("local ls = require('luasnip')\n\nls.add_snippets(\"{}\", {\n\tls.parser.parse_snippet(\n\t\t'{}',\n\t\t'{}'),\n})")
|
||||||
|
file:close()
|
||||||
|
vim.cmd("e " .. filename)
|
||||||
|
vim.bo.filetype = 'lua'
|
||||||
|
-- vim.cmd("Neorg inject-metadata")
|
||||||
|
-- Set an autocmd to return to the previous buffer when the note buffer is closed
|
||||||
|
vim.api.nvim_create_autocmd("BufLeave", {
|
||||||
|
buffer = 0, -- Current buffer (the note buffer)
|
||||||
|
callback = function()
|
||||||
|
load_snippets_from_directory(snippet_path)
|
||||||
|
vim.cmd("buffer " .. previous_buffer)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
print("Captured snippet: " .. filename)
|
||||||
|
end
|
||||||
|
|
||||||
|
function t3_org_capture(name)
|
||||||
|
if type(name) ~= "string" or name == "" then
|
||||||
|
print("Error: Invalid note name")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local timestamp = os.date("%Y%m%d%H%M%S")
|
||||||
|
local org_path = "~/org/.org-roam/"
|
||||||
|
local filename = org_path .. timestamp .. "-" .. name:gsub("%s+", "_") .. ".norg"
|
||||||
|
local file = io.open(vim.fn.expand(filename), "w")
|
||||||
|
if file == nil then
|
||||||
|
print("Error: Could not open file for editing.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local previous_buffer = vim.api.nvim_get_current_buf()
|
||||||
|
file:write("* " .. name .. "\n\n")
|
||||||
|
file:close()
|
||||||
|
vim.cmd("e " .. filename)
|
||||||
|
vim.bo.filetype = 'norg'
|
||||||
|
vim.cmd("Neorg inject-metadata")
|
||||||
|
-- Set an autocmd to return to the previous buffer when the note buffer is closed
|
||||||
|
vim.api.nvim_create_autocmd("BufLeave", {
|
||||||
|
buffer = 0, -- Current buffer (the note buffer)
|
||||||
|
callback = function()
|
||||||
|
vim.cmd("buffer " .. previous_buffer)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
print("Captured note: " .. filename)
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.api.nvim_create_user_command(
|
||||||
|
'NeorgCapture',
|
||||||
|
function()
|
||||||
|
-- local title = vim.fn.input("Title: ")
|
||||||
|
local current_workspace = vim.g.neorg_workspace_name
|
||||||
|
if not current_workspace then
|
||||||
|
vim.cmd("Neorg workspace default")
|
||||||
|
end
|
||||||
|
vim.ui.input({ prompt = "Enter note name: "}, function(note_name)
|
||||||
|
if not note_name or note_name == "" then
|
||||||
|
print("Error: Note name required!")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
t3_org_capture(note_name)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end,
|
||||||
|
{ nargs = 0, desc = "Capture a Neorg note" }
|
||||||
|
)
|
||||||
|
|
||||||
|
vim.api.nvim_create_user_command(
|
||||||
|
'CaptureSnip',
|
||||||
|
function()
|
||||||
|
-- local title = vim.fn.input("Title: ")
|
||||||
|
-- local current_workspace = vim.g.neorg_workspace_name
|
||||||
|
-- if not current_workspace then
|
||||||
|
-- vim.cmd("Neorg workspace default")
|
||||||
|
-- end
|
||||||
|
vim.ui.input({ prompt = "Enter snippet name: "}, function(snip_name)
|
||||||
|
if not snip_name or snip_name == "" then
|
||||||
|
print("Error: Snippet name required!")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
t3_snip_capture(snip_name)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end,
|
||||||
|
{ nargs = 0, desc = "Capture a Neorg note" }
|
||||||
|
)
|
||||||
|
function t3_buffers()
|
||||||
|
fzflua.buffers()
|
||||||
|
end
|
||||||
|
|
||||||
|
function t3_tabs()
|
||||||
|
fzflua.tabs()
|
||||||
|
end
|
||||||
|
|
||||||
|
function t3_live_grep(state)
|
||||||
|
state = state or 0
|
||||||
|
if state == 0 then
|
||||||
|
fzflua.live_grep()
|
||||||
|
else
|
||||||
|
fzflua.live_grep_resume()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function t3_grep(state)
|
||||||
|
state = state or 0
|
||||||
|
if state == 0 then
|
||||||
|
fzflua.grep_project()
|
||||||
|
else
|
||||||
|
fzflua.grep()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function is_netrw_open()
|
||||||
|
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
|
||||||
|
local buf = vim.api.nvim_win_get_buf(win)
|
||||||
|
if vim.bo[buf].filetype == "netrw" then
|
||||||
|
return true, win
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false, nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function t3_toggle_netrw()
|
||||||
|
local is_open, win = is_netrw_open()
|
||||||
|
if is_open then
|
||||||
|
vim.api.nvim_win_close(win, true)
|
||||||
|
else
|
||||||
|
vim.cmd("Lexplore")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.api.nvim_create_autocmd("FileType", {
|
||||||
|
pattern = { "markdown", "norg", "md", "wiki" }, -- Set for markdown file type
|
||||||
|
callback = function()
|
||||||
|
vim.api.nvim_buf_set_keymap(0, "n", "<C-i>", "o* [ ] ", { noremap = true, silent = true })
|
||||||
|
vim.api.nvim_buf_set_keymap(0, "i", "<C-i>", "<Esc>0wi* [ ] ", { noremap = true, silent = true })
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
vim.api.nvim_create_user_command("Split", function()
|
||||||
|
vim.cmd("split")
|
||||||
|
vim.cmd("wincmd j")
|
||||||
|
end, {})
|
||||||
|
|
||||||
|
vim.api.nvim_create_user_command("Vsplit", function()
|
||||||
|
vim.cmd("vsplit")
|
||||||
|
vim.cmd("wincmd l")
|
||||||
|
end, {})
|
||||||
5
home/config/nvim/lua/utils/t3_overrides.lua
Normal file
5
home/config/nvim/lua/utils/t3_overrides.lua
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
-- vim.api.nvim_create_autocmd("winNew", {
|
||||||
|
-- callback = function()
|
||||||
|
-- vim.cmd("wincmd w")
|
||||||
|
-- end,
|
||||||
|
-- })
|
||||||
109
home/config/nvim/lua/vimwiki.lua
Normal file
109
home/config/nvim/lua/vimwiki.lua
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
local vim = vim
|
||||||
|
local opt = vim.opt
|
||||||
|
|
||||||
|
-- opt.wildmenu = true
|
||||||
|
-- vim.g.netrw_keepdir = 0
|
||||||
|
-- vim.treesitter.language.register("markdown", "vimwiki")
|
||||||
|
-- vim.g.vimwiki_folding = 'expr'
|
||||||
|
-- vim.g.vimwiki_header_type = "="
|
||||||
|
|
||||||
|
-- vim.api.nvim_create_autocmd({ "BufWritePost" }, {
|
||||||
|
-- pattern = "*.wiki", -- Adjust this pattern if your Vimwiki files have a different extension
|
||||||
|
-- callback = function()
|
||||||
|
-- vim.cmd("TWSyncTasks")
|
||||||
|
-- end,
|
||||||
|
-- })
|
||||||
|
|
||||||
|
-- Autocommand to trigger LuaSnip snippet expansion for new diary files
|
||||||
|
vim.api.nvim_create_autocmd("BufNewFile", {
|
||||||
|
pattern = "diary/*.wiki", -- Adjust this path to match your diary directory
|
||||||
|
callback = function()
|
||||||
|
-- Expand the 'diary_template' snippet automatically
|
||||||
|
ls.snip_expand(ls.snippets.diary_template[1])
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
vim.g.vimwiki_automatic_nested_syntaxes = 1
|
||||||
|
vim.g.vimwiki_list = {
|
||||||
|
{
|
||||||
|
name = "Personal Wiki",
|
||||||
|
path = '/home/th3r00t/wiki/',
|
||||||
|
path_html = '/home/th3r00t/wiki/html/',
|
||||||
|
syntax = 'default',
|
||||||
|
ext = '.wiki',
|
||||||
|
diary_rel_path = 'diary/',
|
||||||
|
diary_index = "diary_index",
|
||||||
|
auto_tags = 1,
|
||||||
|
auto_toc = 1,
|
||||||
|
auto_export = 1,
|
||||||
|
template_path = "/home/th3r00t/wiki/templates/",
|
||||||
|
template_default = "def_template",
|
||||||
|
template_ext = "html",
|
||||||
|
css_name = "main.css",
|
||||||
|
maxhi = 1, -- BUG: Can be a source of lag.
|
||||||
|
diary_caption_level = 1,
|
||||||
|
bullet_types = { "-", "*", "#", "→" },
|
||||||
|
cycle_bullets = 1,
|
||||||
|
generated_links_caption = 1,
|
||||||
|
listsyms = '✗○◐●✓',
|
||||||
|
-- listsym_rejected = '✗',
|
||||||
|
auto_diary_index = 1,
|
||||||
|
auto_generate_links = 1,
|
||||||
|
auto_generate_tags = 1,
|
||||||
|
exclude_files = { "**/README.md" },
|
||||||
|
rss_name = "feed.rss",
|
||||||
|
base_url = "https://th3r00t.net",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vim.g.vimwiki_syntax_plugins = {
|
||||||
|
codeblock = {
|
||||||
|
["```lua"] = { parser = "lua" },
|
||||||
|
["```python"] = { parser = "python" },
|
||||||
|
["```javascript"] = { parser = "javascript" },
|
||||||
|
["```bash"] = { parser = "bash" },
|
||||||
|
["```html"] = { parser = "html" },
|
||||||
|
["```css"] = { parser = "css" },
|
||||||
|
["```c"] = { parser = "c" },
|
||||||
|
["```zig"] = { parser = "zig" },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
vim.g.vimwiki_toc_header = "Navigation"
|
||||||
|
vim.g.vimwiki_toc_header_level = 2
|
||||||
|
vim.g.vimwiki_hl_cb_checked = 1
|
||||||
|
vim.g.vimwiki_global_ext = 1
|
||||||
|
vim.g.vimwiki_auto_chdir = 1
|
||||||
|
vim.g.wimwiki_markdown_link_ext = 1
|
||||||
|
-- vim.g.vimwiki_folding = 'list'
|
||||||
|
vim.g.vimwiki_folding = 'expr'
|
||||||
|
vim.g.vimwiki_use_calendar = 1
|
||||||
|
vim.api.nvim_set_keymap('n', '<Leader>ww', '<Cmd>VimwikiIndex<CR>', { noremap = true, silent = true })
|
||||||
|
vim.api.nvim_set_keymap('n', '<Leader>wt', '<Cmd>VimwikiTabIndex<CR>', { noremap = true, silent = true })
|
||||||
|
vim.api.nvim_set_keymap('n', '<Leader>ws', '<Cmd>VimwikiUISelect<CR>', { noremap = true, silent = true })
|
||||||
|
local function setup_vimwiki_highlights()
|
||||||
|
-- Define color scheme mappings
|
||||||
|
local colors = {
|
||||||
|
header1 = "#81a1c1", -- Tokyo Night blue
|
||||||
|
header2 = "#88c0d0", -- Tokyo Night light blue
|
||||||
|
header3 = "#8fbcbb", -- Tokyo Night greenish blue
|
||||||
|
bold = "#eceff4", -- Tokyo Night bright white
|
||||||
|
italic = "#5e81ac", -- Tokyo Night dark blue
|
||||||
|
link = "#b48ead", -- Tokyo Night purple
|
||||||
|
list = "#d08770", -- Tokyo Night orange
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Apply highlights for vimwiki syntax elements
|
||||||
|
vim.api.nvim_set_hl(0, "VimwikiHeader1", { fg = colors.header1, bold = true })
|
||||||
|
vim.api.nvim_set_hl(0, "VimwikiHeader2", { fg = colors.header2, bold = true })
|
||||||
|
vim.api.nvim_set_hl(0, "VimwikiHeader3", { fg = colors.header3, bold = true })
|
||||||
|
vim.api.nvim_set_hl(0, "VimwikiBold", { fg = colors.bold, bold = true })
|
||||||
|
vim.api.nvim_set_hl(0, "VimwikiItalic", { fg = colors.italic, italic = true })
|
||||||
|
vim.api.nvim_set_hl(0, "VimwikiLink", { fg = colors.link, underline = true })
|
||||||
|
vim.api.nvim_set_hl(0, "VimwikiList", { fg = colors.list })
|
||||||
|
end
|
||||||
|
setup_vimwiki_highlights()
|
||||||
|
-- Define the Lua function for generating the diary template
|
||||||
|
--
|
||||||
|
vim.pack.add({
|
||||||
|
{ src = "https://github.com/vimwiki/vimwiki", opt = true },
|
||||||
|
})
|
||||||
|
|
||||||
|
vim.cmd.packadd("vimwiki")
|
||||||
Reference in New Issue
Block a user