commit eff7b60f4b9f9c188270cf4299ca98a9582ecec8 Author: root Date: Mon Feb 19 17:15:40 2024 +0100 initial commit diff --git a/alacritty.toml b/alacritty.toml new file mode 100644 index 0000000..57aa399 --- /dev/null +++ b/alacritty.toml @@ -0,0 +1,35 @@ +[window] +opacity=0.8 +dynamic_padding=true + +[font] +#normal={family="Source Code Pro"} +size=10 + +[colors] +[colors.primary] +background="#000000" +foreground="#ffffff" +[colors.normal] +black = "#000000" +red = "#CC0403" +green = "#19CB00" +yellow = "#CECB00" +blue = "#0D73CC" +magenta = "#CB1ED1" +cyan = "#0DCDCD" +white = "#DDDDDD" +[colors.bright] +black = "#767676" +red = "#F2201F" +green = "#23FD00" +yellow = "#FFFD00" +blue = "#1A8FFF" +magenta = "#FD28FF" +cyan = "#14FFFF" +white = "#FFFFFF" + +[keyboard] +bindings = [ +{ key = "Enter", mods = "Super|Shift", action="CreateNewWindow" } +] diff --git a/configuration.nix b/configuration.nix new file mode 100644 index 0000000..9d2ac3b --- /dev/null +++ b/configuration.nix @@ -0,0 +1,172 @@ +# https://search.nixos.org/options and in the NixOS manual (`nixos-help`). + +{ config, lib, pkgs, ... }: + +{ + imports = + [ + ./hardware-configuration.nix + ./home_manager.nix + ]; + + boot.tmp.useTmpfs = true; + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + boot.supportedFilesystems = [ "bcachefs" ]; + boot.kernelPackages = pkgs.linuxPackages_latest; + + networking.hostName = "katvayor"; # Define your hostname. + networking.networkmanager.enable = true; # Easiest to use and most distros use this by default. + time.timeZone = "Europe/Paris"; + + # Configure network proxy if necessary + # networking.proxy.default = "http://user:password@proxy:port/"; + # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; + + # Select internationalisation properties. + i18n.defaultLocale = "en_US.UTF-8"; + console = { + font = "Lat2-Terminus16"; + keyMap = "fr"; + # useXkbConfig = true; # use xkb.options in tty. + }; + + # Enable the X11 windowing system. + # services.xserver.enable = true; + + # security.polkit.enable = true; + # programs.light.enable = true; + nixpkgs.config.pulseaudio = true; + programs.wshowkeys.enable = true; + programs.sway.enable = true; + services.dbus.packages = with pkgs; [ dconf ]; + xdg.portal = { + enable = true; + extraPortals = with pkgs; [ + xdg-desktop-portal-wlr + xdg-desktop-portal-gtk + ]; + }; + nix.settings.experimental-features = [ "nix-command" "flakes" ]; + services.gvfs.enable = true; + programs.thunar.enable = true; + programs.thunar.plugins = with pkgs.xfce; [ + thunar-volman + thunar-archive-plugin + thunar-media-tags-plugin + ]; + + nixpkgs.config.allowUnfree = true; + + # Configure keymap in X11 + # services.xserver.xkb.layout = "us"; + # services.xserver.xkb.options = "eurosign:e,caps:escape"; + + # Enable CUPS to print documents. + # services.printing.enable = true; + + hardware = { + pulseaudio = { + enable = true; + package = pkgs.pulseaudioFull; + }; + bluetooth = { + enable = true; + powerOnBoot = false; + }; + }; + + # Enable touchpad support (enabled default in most desktopManager). + # services.xserver.libinput.enable = true; + + # Define a user account. Don't forget to set a password with ‘passwd’. + users.users.catvayor = { + isNormalUser = true; + extraGroups = [ "wheel" "usb" "networkmanager" "video" "audio" ]; + packages = with pkgs; [ + firefox + tree + ]; + }; + + environment.systemPackages = with pkgs; [ + wget + brightnessctl + nix-search-cli + git + btop + ranger + ]; + + # 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; + }; + + programs.neovim = { + enable = true; + vimAlias = true; + viAlias = true; + defaultEditor = true; + configure = { + customRC = builtins.readFile ./nvim/cfg.vim; + }; + }; + + services.syncthing = { + enable = true; + systemService = true; + dataDir = "/home/catvayor"; + user = "catvayor"; + group = "users"; + openDefaultPorts = true; + settings = { + folders."essentials" = { + path = "~/essentials"; + id = "vgpwu-fk3ct"; + devices = [ "katest" "katel" ]; + }; + devices.katest.id = "UPVXT7D-ZQF4E3J-4WKLLRV-2KF7323-7VOMEJJ-4PZVXW4-UQ2YABE-G7ID4AD"; + devices.katel.id = "DYOKK7J-HZAF5S7-FYTHQF5-UD5GJZ2-4JMV5I5-STUM3HG-5YM2JPR-LATJNAZ"; + }; + }; + + # List services that you want to enable: + + # Enable the OpenSSH daemon. + # services.openssh.enable = true; + + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + # networking.firewall.enable = false; + + # Copy the NixOS configuration file and link it from the resulting system + # (/run/current-system/configuration.nix). This is useful in case you + # accidentally delete configuration.nix. + # system.copySystemConfiguration = true; + + # This option defines the first version of NixOS you have installed on this particular machine, + # and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions. + # + # Most users should NEVER change this value after the initial install, for any reason, + # even if you've upgraded your system to a new NixOS release. + # + # This value does NOT affect the Nixpkgs version your packages and OS are pulled from, + # so changing it will NOT upgrade your system. + # + # This value being lower than the current NixOS release does NOT mean your system is + # out of date, out of support, or vulnerable. + # + # Do NOT change this value unless you have manually inspected all the changes it would make to your configuration, + # and migrated your data accordingly. + # + # For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion . + system.stateVersion = "23.11"; # Did you read the comment? + +} + diff --git a/hardware-configuration.nix b/hardware-configuration.nix new file mode 100644 index 0000000..2f6245e --- /dev/null +++ b/hardware-configuration.nix @@ -0,0 +1,46 @@ +# 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" "vmd" "nvme" "usb_storage" "sd_mod" "rtsx_pci_sdmmc" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/4c1f76c6-5ce6-4987-b15e-9419627b7f19"; + fsType = "bcachefs"; + }; + + boot.initrd.luks.devices."dec-lin" = { + device = "/dev/disk/by-uuid/bba45bff-2356-4ec7-a20c-9cbf9d992822"; + preLVM = true; + allowDiscards = true; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/4F30-BEC7"; + fsType = "vfat"; + }; + + swapDevices = + [ { device = "/dev/disk/by-uuid/5edcb909-6109-4198-84c7-703cbd471b44"; } + ]; + + # 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..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.enp2s0.useDHCP = lib.mkDefault true; + # networking.interfaces.wlp0s20f3.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/home_manager.nix b/home_manager.nix new file mode 100644 index 0000000..dec3f49 --- /dev/null +++ b/home_manager.nix @@ -0,0 +1,244 @@ +{ config, pkgs, lib, ... }: +{ + imports = [ + (import ) + ]; + home-manager.users.catvayor = { + home.stateVersion = "23.11"; + + xdg.configFile."sway/config".onChange = lib.mkForce ""; + + home.sessionVariables = { + MOZ_ENABLE_WAYLAND = "1"; + MOZ_USE_XINPUT2 = "1"; + SDL_VIDEODRIVER = "wayland"; + QT_QPA_PLATFORM = "wayland"; + QT_WAYLAND_DISABLE_WINDOWDECORATION = "1"; + _JAVA_AWT_WM_NONREPARETING = "1"; + XDG_SESSION_TYPE = "wayland"; + XDG_CURRENT_DESKTOP = "sway"; + }; + + home.packages = with pkgs; [ + wl-clipboard + firefox + pavucontrol + font-awesome + libnotify + + discord + signal-desktop + mattermost-desktop + keepassxc + ]; + + programs.thunderbird.enable = true; + programs.thunderbird.profiles = {}; + programs.waybar.enable = true; + home.file.".config/waybar" = { source = ./waybar; recursive = true; }; + programs.alacritty = { enable = true; settings = lib.importTOML ./alacritty.toml; }; + services.mako = { + enable = true; + width = 400; + height = 200; + maxVisible = 5; + backgroundColor = "#8C3586"; + textColor = "#F4F40E"; + borderColor = "#F4F40E"; + defaultTimeout = 5000; + }; + + gtk = { + enable = true; + theme = { package = pkgs.arc-theme; name = "Arc-Dark"; }; + iconTheme = { package = pkgs.arc-icon-theme; name = "Arc"; }; + cursorTheme = { package = pkgs.breeze-hacked-cursor-theme; name = "Breeze_Hacked"; }; + }; + home.pointerCursor = { package = pkgs.breeze-hacked-cursor-theme; name = "Breeze_Hacked"; }; + xdg.enable = true; + + services.swayidle = + let lockwall = pkgs.runCommand "lock_wall.jpg" {} ''${pkgs.ffmpeg}/bin/ffmpeg -i ${./wall.jpg} -filter_complex 'gblur=sigma=3' $out -y''; + in { + enable = true; + timeouts = [ + { + timeout = 300; + command = ''${pkgs.systemd}/bin/loginctl lock-session && ${pkgs.sway}/bin/swaymsg "output * dpms off"''; + resumeCommand = ''${pkgs.sway}/bin/swaymsg "output * dpms on"''; + } + ]; + events = [ + { event = "before-sleep"; command = "${pkgs.systemd}/bin/loginctl lock-session"; } + { event = "lock"; command = "${pkgs.swaylock}/bin/swaylock -f -i ${lockwall}"; } + ]; + }; + wayland.windowManager.sway = { + enable = true; + xwayland = true; + wrapperFeatures = { + base = false; + gtk = false; + }; + extraConfig = ''workspace 1''; + config = + let menuCmd = "${pkgs.wofi}/bin/wofi --show drun -i | xargs swaymsg exec --"; + exitMd = ''Exit Mode:| (l)Log out | (r)Reboot | (p)Poweroff''; + weechatCmd = pkgs.writeShellScript "weechat.sh" '' + nix-shell -p python3 python311Packages.dbus-python python311Packages.notify2 --run 'python ${./weenotify.py} -s' > /dev/null & + while true; do + ssh -R 5431:localhost:5431 weecat@watcher.kat -t screen -xaA -S weechat + sleep 1 + done + ''; + in rec { + window.border = 1; + gaps.smartBorders = "on"; + modifier = "Mod4"; + terminal = "alacritty"; + input."type:keyboard".xkb_layout = "fr"; + startup = [ + { command = "${pkgs.pulseaudio}/bin/pactl set-sink-mute @DEFAULT_SINK@ on"; } + + { command = "discord"; } + { command = "thunderbird"; } + { command = "mattermost-desktop"; } + { command = "signal-desktop --"; } + { command = ''sh -c "sleep 2 && exec keepassxc"''; } + { command = "alacritty --class weechat --title weechat --command ${pkgs.bash}/bin/bash -c ${weechatCmd}"; } + ]; + assigns = { + "1" = [{ app_id="firefox"; }]; + "9" = [{ app_id="thunderbird"; }]; + "10" = [ + { class="Mattermost"; } + { class="Signal"; } + { class="discord"; } + { app_id="weechat"; } + ]; + }; + bars = [{ + command = "waybar"; + mode = "hide"; + }]; + output."*".bg = "${./wall.jpg} fill"; + seat."*"."hide_cursor" = "5000"; + focus.wrapping = "yes"; + window.titlebar = false; + colors = + let black = "#000000"; + dark = "#111111"; + adark = "#111111BB"; + aadark = "#11111177"; + highl = "#222222"; + gray = "#777777"; + white = "#FFFFFF"; + color = "#FFBB00"; + urgent = "#FF0000"; + in { + focused = {border = adark; background = adark; text = white; indicator = color; childBorder = color; }; + unfocused = {border = aadark; background = aadark; text = gray; indicator = dark; childBorder = dark; }; + focusedInactive = {border = adark; background = adark; text = gray; indicator = dark; childBorder = dark; }; + urgent = {border = urgent; background = urgent; text = white; indicator = urgent; childBorder = urgent; }; + }; + modes = { + "display" = { + "Left" = "output - transform 90"; + "Down" = "output - transform normal"; + "Up" = "output - transform 180"; + "Right" = "output - transform 270"; + + "Shift+Left" = "output - transform flipped-90"; + "Shift+Down" = "output - transform flipped"; + "Shift+Up" = "output - transform flipped-180"; + "Shift+Right" = "output - transform flipped-270"; + + "Escape" = ''mode default"''; + }; + + "resize" = { + "Left" = "resize shrink width 10px"; + "Down" = "resize grow height 10px"; + "Up" = "resize shrink height 10px"; + "Right" = "resize grow width 10px"; + + "Escape" = ''mode default"''; + }; + + "${exitMd}" = { + "l" = "exec swaymsg exit"; + "r" = "exec systemctl reboot"; + "p" = "exec systemctl poweroff"; + "Escape" = ''mode default"''; + }; + }; + keybindings = { + "${modifier}+Return" = "exec ${terminal}"; + "${modifier}+q" = "kill"; + "${modifier}+d" = "exec ${menuCmd}"; + "${modifier}+Shift+f" = "exec firefox"; + "${modifier}+Shift+c" = "reload"; + "${modifier}+p" = ''exec ${pkgs.grim}/bin/grim -g "$(${pkgs.slurp}/bin/slurp -d)" - | ${pkgs.wl-clipboard}/bin/wl-copy -t image/png''; + "Print" = "exec ${pkgs.grim}/bin/grim - | ${pkgs.wl-clipboard}/bin/wl-copy -t image/png"; + + "${modifier}+x" = ''mode "display"''; + "${modifier}+r" = ''mode "resize"''; + + "${modifier}+Shift+e" = ''mode "${exitMd}"''; + "${modifier}+l" = "exec ${pkgs.systemd}/bin/loginctl lock-session"; + + "${modifier}+Left" = "focus left"; + "${modifier}+Down" = "focus down"; + "${modifier}+Up" = "focus up"; + "${modifier}+Right" = "focus right"; + "${modifier}+ampersand" = "workspace 1"; + "${modifier}+eacute" = "workspace 2"; + "${modifier}+quotedbl" = "workspace 3"; + "${modifier}+apostrophe" = "workspace 4"; + "${modifier}+parenleft" = "workspace 5"; + "${modifier}+minus" = "workspace 6"; + "${modifier}+egrave" = "workspace 7"; + "${modifier}+underscore" = "workspace 8"; + "${modifier}+ccedilla" = "workspace 9"; + "${modifier}+agrave" = "workspace 10"; + + "${modifier}+Shift+Left" = "move left"; + "${modifier}+Shift+Down" = "move down"; + "${modifier}+Shift+Up" = "move up"; + "${modifier}+Shift+Right" = "move right"; + "${modifier}+Shift+ampersand" = "move container to workspace 1"; + "${modifier}+Shift+eacute" = "move container to workspace 2"; + "${modifier}+Shift+quotedbl" = "move container to workspace 3"; + "${modifier}+Shift+apostrophe" = "move container to workspace 4"; + "${modifier}+Shift+parenleft" = "move container to workspace 5"; + "${modifier}+Shift+minus" = "move container to workspace 6"; + "${modifier}+Shift+egrave" = "move container to workspace 7"; + "${modifier}+Shift+underscore" = "move container to workspace 8"; + "${modifier}+Shift+ccedilla" = "move container to workspace 9"; + "${modifier}+Shift+agrave" = "move container to workspace 10"; + + "${modifier}+b" = "splith"; + "${modifier}+v" = "splitv"; + "${modifier}+Shift+s" = "layout stacking"; + "${modifier}+w" = "layout tabbed"; + "${modifier}+s" = "layout toggle split"; + + "${modifier}+f" = "fullscreen"; + "${modifier}+Shift+space" = "floating toggle"; + "${modifier}+space" = "focus mode toggle"; + "${modifier}+z" = "focus parent"; + "${modifier}+Shift+z" = "focus child"; + "${modifier}+Shift+F1" = "move scratchpad"; + "${modifier}+F1" = "scratchpad show"; + + "XF86AudioRaiseVolume" = "exec ${pkgs.pulseaudio}/bin/pactl set-sink-volume @DEFAULT_SINK@ +5%"; + "XF86AudioLowerVolume" = "exec ${pkgs.pulseaudio}/bin/pactl set-sink-volume @DEFAULT_SINK@ -5%"; + "XF86AudioMute" = "exec ${pkgs.pulseaudio}/bin/pactl set-sink-mute @DEFAULT_SINK@ toggle"; + "XF86AudioMicMute" = "exec ${pkgs.pulseaudio}/bin/pactl set-source-mute @DEFAULT_SOURCE@ toggle"; + "XF86MonBrightnessDown" = "exec ${pkgs.brightnessctl}/bin/brightnessctl set 5%-"; + "XF86MonBrightnessUp" = "exec ${pkgs.brightnessctl}/bin/brightnessctl set +5%"; + }; + }; + }; + }; +} diff --git a/nvim/cfg.vim b/nvim/cfg.vim new file mode 100644 index 0000000..fb9de5a --- /dev/null +++ b/nvim/cfg.vim @@ -0,0 +1,160 @@ +let &packpath = &runtimepath +filetype plugin indent on +syntax enable + +" Use :help 'option' to see the documentation for the given option. + +set autoindent +set backspace=indent,eol,start +set complete-=i +set smarttab + +let g:mapleader=";" + +set nrformats-=octal + +set ttimeout +set ttimeoutlen=100 + +set incsearch + +" Use to clear the highlighting of :set hlsearch. +if maparg('', 'n') ==# '' + nnoremap :nohlsearch +endif + +set laststatus=2 +set ruler +set showcmd +set wildmenu + +if !&scrolloff + set scrolloff=1 +endif +if !&sidescrolloff + set sidescrolloff=5 +endif +set display+=lastline + +if &listchars ==# 'eol:$' + set listchars=tab:>\ ,trail:-,extends:>,precedes:<,nbsp:+ +endif + +if v:version > 703 || v:version == 703 && has("patch541") + set formatoptions+=j " Delete comment character when joining commented lines +endif + +if has('path_extra') + setglobal tags-=./tags tags^=./tags; +endif + +set autoread + +if &history < 1000 + set history=1000 +endif +if &tabpagemax < 50 + set tabpagemax=50 +endif +if !empty(&viminfo) + set viminfo^=! +endif +set sessionoptions-=options + +" Allow color schemes to do bright colors without forcing bold. +if &t_Co == 8 && $TERM !~# '^linux' + set t_Co=16 +endif + +" Load matchit.vim, but only if the user hasn't installed a newer version. +if !exists('g:loaded_matchit') && findfile('plugin/matchit.vim', &rtp) ==# '' + runtime! macros/matchit.vim +endif + +inoremap u +set mouse=a +vmap "*ygv + +set tabstop=2 +set shiftwidth=2 +set expandtab + +syntax enable + +" let g:coqtail_nomap = 1 +" +" function Coqfun(count, cmd) +" if a:count == 0 +" let l:count=1 +" else +" let l:count=a:count +" endif +" execute a:cmd . l:count +" endfunction +" +" map :CoqStart +" map :CoqStop +" map :call Coqfun(v:count,"CoqNext") +" map :call Coqfun(v:count,"CoqUndo") +" map :CoqToLine +" imap :call Coqfun(v:count,"CoqNext") +" imap :call Coqfun(v:count,"CoqUndo") +" imap :CoqToLine +" +" au BufRead,BufNewFile *.lus,*.ept setlocal filetype=lustre + +""""""""""""""""""""""""""""""""" Colors +nnoremap ak$ + +set background=dark +hi clear +if exists("syntax_on") + syntax reset +endif +let g:colors_name = "perso" + +set cursorline +set number +set relativenumber + +autocmd InsertEnter * set relativenumber! +autocmd InsertLeave * set relativenumber! + +map :set number! +map :set relativenumber! + +hi Normal guifg=cyan guibg=black +hi NonText guifg=yellow guibg=#303030 +hi comment guifg=green +hi constant guifg=cyan gui=bold +hi identifier guifg=cyan gui=NONE +hi statement guifg=lightblue gui=NONE +hi preproc guifg=Pink2 +hi type guifg=seagreen gui=bold +hi special guifg=yellow +hi ErrorMsg guifg=Black guibg=Red +hi WarningMsg guifg=Black guibg=Green +hi Error guibg=Red +hi Todo guifg=Black guibg=orange +hi Cursor guibg=#60a060 guifg=#00ff00 +hi Search guibg=darkgray guifg=black gui=bold +hi IncSearch gui=NONE guibg=steelblue +hi LineNr guifg=darkgrey ctermbg=234 ctermfg=141 +hi CursorLine cterm = NONE +hi CursorLineNR cterm=NONE ctermbg=black +hi title guifg=darkgrey +hi ShowMarksHL ctermfg=cyan ctermbg=lightblue cterm=bold guifg=yellow guibg=black gui=bold +hi StatusLineNC gui=NONE guifg=lightblue guibg=darkblue +hi StatusLine gui=bold guifg=cyan guibg=blue +hi label guifg=gold2 +hi operator guifg=orange +hi clear Visual +hi Visual term=reverse cterm=reverse gui=reverse +hi DiffChange guibg=darkgreen +hi DiffText guibg=olivedrab +hi DiffAdd guibg=slateblue +hi DiffDelete guibg=coral +hi Folded guibg=gray30 +hi FoldColumn guibg=gray30 guifg=white +hi cIf0 guifg=gray +hi diffOnly guifg=red gui=bold diff --git a/wall.jpg b/wall.jpg new file mode 100644 index 0000000..37b1954 Binary files /dev/null and b/wall.jpg differ diff --git a/waybar/config b/waybar/config new file mode 100644 index 0000000..7976ffd --- /dev/null +++ b/waybar/config @@ -0,0 +1,158 @@ +// Global +{ + "layer": "top", + "position": "bottom", + "ipc": true, + + // If height property would be not present, it'd be calculated dynamically + //"height": 20, + + "modules-left": [ + //"custom/launcher", + "sway/workspaces", + "sway/mode", + ], + + "modules-center": [ + ], + + "modules-right": [ + "network", + "idle_inhibitor", + "memory", + "cpu", + "pulseaudio", + "custom/keyboard-layout", + "battery", + "backlight", + "tray", + //"custom/power", + "clock", + ], + + // Modules + + "idle_inhibitor": { + "format": "{icon}", + "format-icons":{ + "activated": "", + "deactivated": "" + } + }, + + "battery": { + "states": { + "good": 100, + "warning": 30, + "critical": 15 + }, + "format": "{capacity}% {icon}", + "format-charging": "{capacity}% ", + "format-plugged": "{capacity}% ", + // "format-good": "", // An empty format will hide the module + // "format-full": "", + "format-icons": ["", "", "", "", ""] + }, + + "clock": { + "interval": 1, + "format": "{:%d-%m-%Y %H:%M:%OS}", + }, + + "cpu": { + "interval": 1, + "format": "{icon0}{icon1}{icon2}{icon3}{icon4}{icon5}{icon6}{icon7} {avg_frequency:0.1f}GHz ", // Icon: microchip + "format-icons": ["▁", "▂", "▃", "▄", "▅", "▆", "▇", "█"], + "states": { + "warning": 70, + "critical": 90, + }, + "on-click": "xfce4-terminal -e 'top'", + }, + + "custom/keyboard-layout": { + "exec": "swaymsg -t get_inputs | grep -m1 'xkb_active_layout_name' | cut -d '\"' -f4 | head -c2", + "interval": 30, // Interval set only as a fallback, as the value is updated by signal + "format": "{} ", // Icon: keyboard + "signal": 1, // SIGHUP, Signal sent by Sway key binding (~/.config/sway/key-bindings) + "tooltip": false, + "on-click": "swaymsg input 1:1:AT_Translated_Set_2_keyboard xkb_switch_layout next", + }, + + "memory": { + "interval": 5, + "format" : "{icon} ", + "tooltip" : true, + "tooltip-format": "{used:0.1f}/{total:0.1f}G, swap {swapUsed:0.1f}/{swapTotal:0.1f}G", + "format-icons": ["▁", "▂", "▃", "▄", "▅", "▆", "▇", "█"], + "on-click": "xfce4-terminal -e 'htop'", + "states": { + "warning": 70, + "critical": 90 + } + }, + + "network": { + "interval": 5, + "format-wifi": "{essid}: {signalStrength}% ", // Icon: wifi + "format-ethernet": "", // Icon: ethernet + "format-disconnected": "", + "tooltip-format": "{ifname}: {ipaddr}", + "tooltip-format-disconnected": "Disconnected", + "on-click": "xfce4-terminal -e 'nmtui'", + "on-click-right": "wl-copy $(ip -json route get 8.8.8.8 | jq -r '.[].prefsrc')", // copy ip-address + }, + + "sway/mode": { + "format": "{}", + "tooltip": false + }, + + "sway/workspaces": { + "disable-scroll": true, + "disable-markup" : false, + "all-outputs": true, + "format":"{icon}", + "format-icons": { + //"3": "", + //"4": "", + //"5": "", + //"6": "", + } + }, + + "pulseaudio": { + "scroll-step": 1, // %, can be a float + "format": "{volume}% {icon}", + "format-bluetooth": "{volume}% {icon}  {format_source}", + "format-bluetooth-muted": "× {icon}  {format_source}", + "format-muted": "×", + "format-source": "{volume}% ", + "format-source-muted": "", + "format-icons": { + "headphone": "", + "hands-free": "וֹ", + "headset": "  ", + "phone": "", + "portable": "", + "car": "", + "default": [""] + }, + "on-click": "pavucontrol", + "on-scroll-up": "pamixer -ui 2", + "on-scroll-down": "pamixer -ud 2", + }, + + "tray": { + "icon-size": 18, + "spacing":10, + }, + + "backlight" :{ + "scroll-step": 1, // %, can be a float + "format": "{percent}% {icon}", + "format-icons": [""], + "on-scroll-down": "brightnessctl -c backlight set 1%-", + "on-scroll-up": "brightnessctl -c backlight set +1%" + }, +} diff --git a/waybar/style.css b/waybar/style.css new file mode 100644 index 0000000..724c20b --- /dev/null +++ b/waybar/style.css @@ -0,0 +1,196 @@ +/* ============================================================================= + * + * Waybar configuration + * + * Configuration reference: https://github.com/Alexays/Waybar/wiki/Configuration + * + * =========================================================================== */ + +/* ----------------------------------------------------------------------------- + * Keyframes + * -------------------------------------------------------------------------- */ + +@define-color highlight #ffbb00 ; +@define-color base1 #111111 ; +@define-color lgray #cccccc ; +@define-color dgray #777777 ; +@define-color urgent #ee1100 ; + +@keyframes blink-warning { + 70% { + color: white; + } + + to { + color: white; + background-color: orange; + } +} + +@keyframes blink-critical { + 70% { + color: white; + } + + to { + color: white; + background-color: red; + } +} + +/* ----------------------------------------------------------------------------- + * Base styles + * -------------------------------------------------------------------------- */ + +/* Reset all styles */ +* { + border: none; + border-radius: 0; + min-height: 0; + margin: 0px; + padding: 0; + all: unset; +} + +/* The whole bar */ +#waybar { + background: transparent; + color: #bebebe; + background-color: @base1; + font-family: "Ubuntu", "Font Awesome 6 Free-Solid"; +/* font-weight: bold; */ + font-size: 14px; +} + +/* Every modules */ +#battery, +#clock, +#backlight, +#cpu, +#custom-keyboard-layout, +#memory, +#mode, +#custom-weather, +#network, +#pulseaudio, +#temperature, +#tray, +#idle_inhibitor, +#custom-PBPbattery { + padding:0.0rem 1rem; + margin: 0px 0px; +} + +/* ----------------------------------------------------------------------------- + * Modules styles + * -------------------------------------------------------------------------- */ + +#battery { + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-direction: alternate; +} + +#battery.warning { + color: orange; +} + +#battery.critical { + color: red; +} + +/* +#battery.warning.discharging { + animation-name: blink-warning; + animation-duration: 3s; +} + +#battery.critical.discharging { + animation-name: blink-critical; + animation-duration: 2s; +} +*/ + +#cpu.warning { + color: orange; +} + +#cpu.critical { + color: red; +} + +#memory { + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-direction: alternate; +} + +#memory.warning { + color: orange; +} + +#memory.critical { + color: red; + animation-name: blink-critical; + animation-duration: 2s; +} + +#mode { + background: @highlight; + border-bottom: 3px transparent; + color:white; +} + +#network.disconnected { + color: orange; +} + +#temperature.critical { + color: red; +} + +#workspaces { + font-size:14px; + margin: 2px; + margin-top: 2px; +} + +#workspaces button { + border-bottom: 0px solid transparent; + padding-bottom: 2px; + padding-top: 3px; + min-width: 20px; + margin-right: 1px; + color: @lgray; + opacity: 0.5; +} + +#workspaces button.current_output { + opacity: 1; +} + +#workspaces button.visible { + border-bottom: 3px solid @lgray; + padding-top: 0px; +} + +#workspaces button.focused { + border-bottom: 3px solid transparent; + padding-bottom: 3px; +} + +#workspaces button.current_output.visible { + border-bottom: 3px solid @dgray; + padding-top: 0px; +} + +#workspaces button.current_output.focused { + border-bottom: 3px solid @highlight; + padding-top: 0px; +} + +#workspaces button.urgent { + border-bottom: 3px solid @urgent; + padding-top: 0px; + color: @urgent; +} diff --git a/weenotify.py b/weenotify.py new file mode 100644 index 0000000..c51c1aa --- /dev/null +++ b/weenotify.py @@ -0,0 +1,294 @@ +# BSD 2-Clause License +# +# Copyright (c) 2018, Elia El Lazkani +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +""" +Local mode dependencies: + - weechat + - dbus-python + - notify2 + +Remote mode dependencies: + - weechat + +Server mode dependencies: + - dbus-python + - notify2 + +This script acts as both server and weechat plugin. One can configure it to run +locally on the box in which case it will use *notify2* to send notifications +through dbus to the user. Or, one can run it in remote mode where both +the _host_ and the _port_ need to be configured to send notifications to the server. + +If you are running weechat in an ssh session, you can do the following: +> ssh -R 5431:localhost:5431 user@host + +The above will ssh tunnel port 5431 between guest and host and notifications can be +sent to the server running locally on your machine. + +To run the server, do the following: +> python weenotify.py -s + +One can get the full script help print with: +> python weenotify.py -h +""" + +import json +import socket +import argparse + +try: + import notify2 as Notify + import dbus + notify_imported = True + dbus_imported = True +except ImportError: + try: + import dbus + dbus_imported = True + except ImportError: + dbus_imported = False + notify_imported = False + +try: + import weechat as w + weechat_imported = True +except ImportError: + weechat_imported = False + +SCRIPT_NAME = "weenotify" +SCRIPT_AUTHOR = "Elia El Lazkani " +SCRIPT_VERSION = "0.4" +SCRIPT_LICENSE = "BSD-2-Clause" +SCRIPT_DESCRIPTION = "Plugin/Server to send/receive notifications and display them" + +def listener(sockt): + """ Method to handle incoming data from client """ + conn, addr = sockt.accept() + try: + data = "" + _partial = conn.recv(1024).decode('utf-8') + while _partial: + data += _partial + _partial = conn.recv(1024).decode('utf-8') + except Exception: + conn.close() + return + + if data: + print("{}: {}".format(addr, data.strip('\n'))) + notify(json.loads(data.strip())) + +def server(host, port): + """ Method to run the server in a loop """ + print("Starting server...") + host = host if host else '' + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.bind((host, port)) + s.listen(5) + if host: + print("Server listening on {}:{}...".format(host, port)) + else: + print("Server listening locally on port {}...".format(port)) + + try: + while True: + listener(s) + except KeyboardInterrupt: + print("Shutting down server...") + finally: + s.close() + +def notify(data): + """ Method to notify the user through dbus """ + if data['prefix'] != '--': + try: + msg = "{} => {}: {}".format(data['buffer'], + data['prefix'], + data['message']) + except UnicodeEncodeError: + # Yey to python2 + msg = "{} => {}: {}".format(data['buffer'], + data['prefix'], + data['message'].encode('utf-8')) + else: + try: + msg = "{} => {}".format(data['buffer'], + data['message']) + except UnicodeEncodeError: + # Woohoo python2 + msg = "{} => {}".format(data['buffer'], + data['message'].encode('utf-8')) + Notify.init(SCRIPT_NAME) + notification = Notify.Notification(data['type'], msg) + try: + notification.show() + except dbus.exceptions.DBusException as e: + print(e) + pass + +def local_notify(data): + """ Method to send notification locally on the host """ + if notify_imported: + notify(data) + else: + if dbus_imported: + w.prnt("", "notify2 could not be imported, disabling {}" + .format(SCRIPT_NAME)) + else: + w.prnt("", "notify2 could not be imported due to missing dbus-python," + "disabling {}".format(SCRIPT_NAME)) + w.config_set_plugin('enable', 'off') + +def send(host, port, msg): + """ Method to send data to the server for notification display """ + c = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + try: + c.connect((host, port)) + except Exception: + c.close() + return + message = "{}".format(json.dumps(msg)) + message = str.encode(message, 'utf-8') + c.sendall(message) + c.close() + +def on_notify(data, buffer, date, tags, displayed, + highlight, prefix, message): + """ Method to take action on client notification """ + enable = w.config_get_plugin('enable') + if enable.lower() == 'on': + data = weechat_parser(data, buffer, date, tags, displayed, + highlight, prefix, message) + if data: + mode = w.config_get_plugin('mode') + if mode.lower() == 'remote': + host = w.config_get_plugin('host') + port = int(w.config_get_plugin('port')) + send(host, port, data) + else: + local_notify(data) + return w.WEECHAT_RC_OK + +def weechat_parser(data, buffer, date, tags, displayed, + highlight, prefix, message): + """ Method to parte data coming from weechat and take action on it """ + buffer_name = w.buffer_get_string(buffer, 'short_name') + if "NOTICE" in data and buffer_name != "highmon": + if buffer_name == prefix: + buffer_name = data + return { 'buffer': buffer_name, + 'type': data, + 'prefix': prefix, + 'message': message } + elif "PRIVMSG" in data and "irc_notice" not in tags: + return { 'buffer': buffer_name, + 'type': data, + 'prefix': prefix, + 'message': message } + elif "MSG" in data and int(highlight) and \ + "irc_notice" not in tags: + return { 'buffer': buffer_name, + 'type': data, + 'prefix': prefix, + 'message': message } + +def client(): + """ Method to register the plugin and hook into weechat """ + settings = { + 'enable': { + 'description': 'Enable/Disable notifications.', + 'values': ['off', 'on'], + 'default': 'off' + }, + 'mode': { + 'description': 'Set whether notifications need to be' + 'sent locally or to an external server.', + 'values': ['local', 'remote'], + 'default': 'local' + }, + 'host': { + 'description': 'Set the server host to send notifications to.', + 'values': None, + 'default': 'localhost' + }, + 'port': { + 'description': 'Set the server port to use to send notifcation.', + 'values': None, + 'default': '5431' + } + } + + if w.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, + SCRIPT_DESCRIPTION, '', ''): + for option, value in settings.items(): + if not w.config_is_set_plugin(option): + w.config_set_plugin(option, value['default']) + if value.get('values', None): + w.config_set_desc_plugin(option, '{} (values: [{}], default: {})'.format( + value['description'], '/'.join(value['values']), value['default'])) + else: + w.config_set_desc_plugin(option, '{} (default: {})'.format( + value['description'], value['default'])) + w.hook_print('', 'notify_message', '', 1, 'on_notify', 'MSG') + w.hook_print('', 'notify_private', '', 1, 'on_notify', 'PRIVMSG') + w.hook_print('', 'irc_notice', '', 1, 'on_notify', 'NOTICE') + +def argument_parse(): + """ Method to parse command line arguments """ + parser = argparse.ArgumentParser( + description=SCRIPT_DESCRIPTION) + + parser.add_argument( + '-s', '--server', action='store_true', + help='Run in server mode.') + parser.add_argument( + '-H', '--host', type=str, default='', + help='The host/IP to bind to.') + parser.add_argument( + '-p', '--port', type=int, default=5431, + help='The port to listen to.') + parser.add_argument( + '-V', '--version', action='version', + version='%(prog)s {}'.format(SCRIPT_VERSION), + help='Prints version.') + return parser + +if __name__ == '__main__': + parser = argument_parse() + args = parser.parse_args() + if args.server: + if notify_imported: + server(args.host, args.port) + else: + if dbus_imported: + print("notify2 could not be imported") + else: + print("notify2 was not imported due to missing dbus-python") + else: + if weechat_imported: + client() + else: + print("weechat could not be imported, make sure weechat is running this")