diff --git a/flake.nix b/flake.nix index 833cf30..d9c45d3 100644 --- a/flake.nix +++ b/flake.nix @@ -57,12 +57,26 @@ }; }; + fg42-wm = pkgs.callPackage ./nix/fg42 { + inherit nixpkgs; + modules = [ + ./nix/modules/editor + ./nix/modules/elisp + ./nix/modules/graphics + ./nix/modules/noether + ./nix/modules/wm + ]; + extraPackages = { + noether = inputs.noether.outputs.packages.${system}.default; + }; + }; + run-test-wm = pkgs.writeShellApplication { name = "run-test-wm"; - runtimeInputs = [ fg42 ]; + runtimeInputs = [ fg42-wm ]; text = '' - DISPLAY=:1 ${fg42}/bin/fg42-wm + DISPLAY=:1 ${fg42-wm}/bin/fg42-wm ''; }; @@ -70,11 +84,12 @@ { packages = { default = fg42; + wm = fg42-wm; }; devShells.default = pkgs.mkShell { - nativeBuildInputs = [ fg42 pkgs.fish test-x run-test-wm ]; - buildInputs = [ fg42 ]; + nativeBuildInputs = [ fg42 fg42-wm pkgs.fish test-x run-test-wm ]; + buildInputs = [ fg42 fg42-wm ]; }; apps.wm = { diff --git a/nix/fg42/default.nix b/nix/fg42/default.nix index e8a1778..746650f 100644 --- a/nix/fg42/default.nix +++ b/nix/fg42/default.nix @@ -30,17 +30,23 @@ let then modules else import ../modules { - inherit pkgs; - lib = lib; + inherit pkgs lib; }; + pkgsModule = { config, ... }: { + config = { + _module.args.baseModules = modules; + _module.args.pkgs = lib.mkDefault pkgs; + _module.check = true; + }; + }; utils = pkgs.callPackage ./utils.nix { }; final = lib.evalModules { # The unit module is mandatory and the bare min # config that is necessary - modules = [ ../modules/unit ] ++ fg42Modules ++ extraModules; + modules = [ ../modules/unit ] ++ fg42Modules ++ extraModules ++ [ pkgsModule ]; specialArgs = { inherit utils; inherit (utils) makeFG42Drv; diff --git a/nix/modules/default.nix b/nix/modules/default.nix index d0a7a8d..85f8a8a 100644 --- a/nix/modules/default.nix +++ b/nix/modules/default.nix @@ -34,13 +34,5 @@ let ./c-family ./python ]; - - pkgsModule = { config, ... }: { - config = { - _module.args.baseModules = modules; - _module.args.pkgs = lib.mkDefault pkgs; - _module.check = true; - }; - }; in -modules ++ [ pkgsModule ] +modules diff --git a/nix/modules/wm/default.nix b/nix/modules/wm/default.nix new file mode 100644 index 0000000..8524f42 --- /dev/null +++ b/nix/modules/wm/default.nix @@ -0,0 +1,51 @@ +# Fg42 - Emacs Editor for advance users +# +# Copyright (c) 2010-2024 Sameer Rahmani +# +# 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, version 2. +# +# 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, see . + +# This is the home manager module that exposes FG42. It differs +# from FG42 modules that are structurally the same but used in +# different context + +# A list of default FG42 modules to build FG42 with. +{ lib, config, pkgs, makeFG42Drv, ... }: +with lib; +let + cfg = config.fg42.wm; + + deps = + (with pkgs.emacsPackages; [ + exwm + ]); + + drv = makeFG42Drv { + pname = "wm"; + version = config.fg42.version; + buildInputs = deps; + src = ./.; + }; +in +{ + options.fg42.wm.enable = mkAndEnableOption "wm"; + + config = mkIf cfg.enable { + fg42.elispPackages = [ drv ] ++ deps; + + fg42.paths = (with pkgs;[ + dunst + ]); + + fg42.requires = [ drv.pname ]; + }; +} diff --git a/nix/modules/wm/lisp/fg42/wm.el b/nix/modules/wm/lisp/fg42/wm.el new file mode 100644 index 0000000..a4255b2 --- /dev/null +++ b/nix/modules/wm/lisp/fg42/wm.el @@ -0,0 +1,174 @@ +;;; FG42 --- The mighty editor for the emacsians -*- lexical-binding: t; -*- +;; +;; Copyright (c) 2010-2024 Sameer Rahmani & Contributors +;; +;; Author: Sameer Rahmani +;; URL: https://devheroes.codes/FG42/FG42 +;; Version: 4.0.0 +;; +;; 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 3 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, see . +;; +;;; Commentary: +;;; Code: +(eval-when-compile + (require 'fpkg) + (require 'fg42/config)) + + +(defvar workspace-configuration + (list 0 "HDMI-1" + 1 "HDMI-1" + 2 "HDMI-1" + 3 "HDMI-1" + 4 "HDMI-1" + 5 "HDMI-1" + 6 "HDMI-1" + 7 "HDMI-1" + 8 "HDMI-1" + 9 "HDMI-1") + "Workspace configuration for EXWM. (default 10 screens on HDMI-1).") + +;; TODO: Document this +;; (add-hook 'exwm-randr-screen-change-hook +;; (lambda () +;; (start-process-shell-command +;; "xrandr" nil "xrandr --output HDMI-1 --above eDP-1 --mode 1920x1080"))) + + +(when-wm + (use! exwm-randr + "EXWM plugin to interact with xrandr." + :commands exwm-randr-enable + :config + (setq exwm-randr-workspace-output-plist workspace-configuration)) + + + (use! exwm-systemtray + "Enables systemtray on EXWM" + :commands exwm-systemtray-enable) + + + ;; (use! mini-frame + ;; "Place minibuffer at the top of the current frame on `read-from-minibuffer'." + ;; :hook (emacs-startup . mini-frame-mode) + ;; :custom + ;; (mini-frame-show-parameters + ;; '((top . 10) + ;; (width . 0.5) + ;; (left . 0.5) + ;; (height . 15)))) + + + (use! exwm + "Emacs X Widnow manager." + :commands exwm-enable + :config + (require 'exwm-config) + (exwm-config-ido) + + ;; Set the initial number of workspaces (they can also be created later). + (setq exwm-workspace-number 10) + ;; All buffers created in EXWM mode are named "*EXWM*". You may want to + ;; change it in `exwm-update-class-hook' and `exwm-update-title-hook', which + ;; are run when a new X window class name or title is available. Here's + ;; some advice on this topic: + ;; + Always use `exwm-workspace-rename-buffer` to avoid naming conflict. + ;; + For applications with multiple windows (e.g. GIMP), the class names of + ;; all windows are probably the same. Using window titles for them makes + ;; more sense. + ;; In the following example, we use class names for all windows except for + ;; Java applications and GIMP. + (add-hook 'exwm-update-class-hook + (lambda () + (unless (or (string-prefix-p "sun-awt-X11-" exwm-instance-name) + (string= "gimp" exwm-instance-name)) + (exwm-workspace-rename-buffer exwm-class-name)))) + + (add-hook 'exwm-update-title-hook + (lambda () + (when (or (not exwm-instance-name) + (string-prefix-p "sun-awt-X11-" exwm-instance-name) + (string= "gimp" exwm-instance-name)) + (exwm-workspace-rename-buffer exwm-title)))) + + ;; Global keybindings can be defined with `exwm-input-global-keys'. + ;; Here are a few examples: + (setq exwm-input-global-keys + `( + ;; Bind "s-r" to exit char-mode and fullscreen mode. + ([?\s-r] . exwm-reset) + ([?\s-g] . keyboard-quit) + ([8388640] . other-window) + ;; Bind "s-w" to switch workspace interactively. + ([?\s-w] . exwm-workspace-switch) + ;; Bind "s-0" to "s-9" to switch to a workspace by its index. + ,@(mapcar (lambda (i) + `(,(kbd (format "s-%d" i)) . + (lambda () + (interactive) + (exwm-workspace-switch-create ,i)))) + (number-sequence 0 9)) + ;; Bind "s-&" to launch applications ('M-&' also works if the output + ;; buffer does not bother you). + ([?\s-d] . (lambda (command) + (interactive (list (read-shell-command "$ "))) + (start-process-shell-command command nil command))) + ;; Bind "s-" to "slock", a simple X display locker. + ([s-f2] . (lambda () + (interactive) + (start-process "" nil "slock"))))) + + ;; To add a key binding only available in line-mode, simply define it in + ;; `exwm-mode-map'. The following example shortens 'C-c q' to 'C-q'. + (define-key exwm-mode-map [?\C-q] #'exwm-input-send-next-key) + + (push ?\C-c exwm-input-prefix-keys) + + ;; You can hide the minibuffer and echo area when they're not used, by + ;; uncommenting the following line. + ;;(setq exwm-workspace-minibuffer-position 'bottom) + + ;; The following example demonstrates how to use simulation keys to mimic + ;; the behavior of Emacs. The value of `exwm-input-simulation-keys` is a + ;; list of cons cells (SRC . DEST), where SRC is the key sequence you press + ;; and DEST is what EXWM actually sends to application. Note that both SRC + ;; and DEST should be key sequences (vector or string). + (setq exwm-input-simulation-keys + `( + ;; movement + (,(kbd "C-b") . left) + (,(kbd "M-b") . ,(kbd "C-")) + (,(kbd "C-f") . right) + (,(kbd "M-f") . ,(kbd "C-")) + (,(kbd "C-p") . up) + (,(kbd "C-n") . down) + (,(kbd "C-a") . home) + (,(kbd "C-e") . end) + (,(kbd "M-v") . prior) + (,(kbd "C-v") . next) + (,(kbd "C-d") . delete) + ;;(,(kbs "C-k") . [S-end delete]) + ;; navigation + (,(kbd "C-c b") . ,(kbd "M-")) + (,(kbd "C-c f") . ,(kbd "M-")) + (,(kbd "C-c w") . ,(kbd "C-w")) + (,(kbd "C-w") . ,(kbd "C-x")) + (,(kbd "M-w") . ,(kbd "C-c")) + (,(kbd "C-y") . ,(kbd "C-v")) + ;; search + (,(kbd "C-s") . ,(kbd "C-f")))))) + + +(provide 'fg42/wm) +;;; wm.el ends here