diff --git a/config/fonts.nix b/config/fonts.nix index 004b1ab..2d83ba8 100644 --- a/config/fonts.nix +++ b/config/fonts.nix @@ -8,7 +8,8 @@ mkIf (elem "fonts" config.machine.conffiles) { enableGhostscriptFonts = true; fontconfig = { enable = true; - ultimate.enable = true; + # deprecated (will eventually be completely removed) + # ultimate.enable = true; includeUserConf = false; }; fonts = with pkgs; [ diff --git a/machines/Lilim/options.nix b/machines/Lilim/options.nix index 239686f..2ab17b3 100644 --- a/machines/Lilim/options.nix +++ b/machines/Lilim/options.nix @@ -21,7 +21,18 @@ with lib; "base" "dict" "emacs" - "emacs::solarized-theme" + "emacs::doom-themes" + "emacs::doom-modeline" + # "emacs::solarized-theme" + "emacs::company" + "emacs::flyspell" + "emacs::flycheck" + # "emacs::powerline" + "emacs::nix-mode" + "emacs::magit" + "emacs::org" + "emacs::elpy" +# "emacs::rust" "extra" "cpp" "haskell" @@ -38,6 +49,8 @@ with lib; firewall = { enable = true; allowPing = true; + allowedUDPPorts = [ 24642 ]; + allowedTCPPorts = [ 24642 ]; allowedUDPPortRanges = [ { from = 1714; to = 1764; } ]; allowedTCPPortRanges = [ { from = 1714; to = 1764; } ]; }; diff --git a/options/emacs-init.nix b/options/emacs-init.nix index 8c15687..af5d85e 100644 --- a/options/emacs-init.nix +++ b/options/emacs-init.nix @@ -389,22 +389,23 @@ in }; config = mkIf cfg.enable { - environment.systemPackages = let - finalPackage = (pkgs.emacsWithPackages (epkgs: - let - getPkg = v: - if isFunction v then [ (v epkgs) ] - else optional (isString v && hasAttr v epkgs) epkgs.${v}; - in - [ epkgs.use-package ] - ++ optional hasBind epkgs.bind-key - ++ optional hasBind epkgs.diminish - ++ ( - concatMap (v: getPkg (v.package)) - (builtins.attrValues cfg.usePackage) - ))); - in [ - ((pkgs.emacsPackagesNgGen finalPackage).trivialBuild { + machine.pkgsets.emacs.pkgs = epkgs: + let + getPkg = v: + if isFunction v then [ (v epkgs) ] + else optional (isString v && hasAttr v epkgs) epkgs.${v}; + in + [ epkgs.use-package ] + ++ optional hasBind epkgs.bind-key + ++ optional hasBind epkgs.diminish + ++ ( + concatMap (v: getPkg (v.package)) + (builtins.attrValues cfg.usePackage) + ); + machine.pkgsets.emacs.pkgwrap = (pkgs.emacsWithPackages config.machine.pkgsets.emacs.pkgs); + + environment.systemPackages = [ + ((pkgs.emacsPackagesNgGen config.machine.pkgsets.emacs.pkgwrap).trivialBuild { pname = "hm-init"; version = "0"; src = pkgs.writeText "hm-init.el" initFile; @@ -413,6 +414,7 @@ in }) ]; + # This has no effect, will have to add a wrapper to emacs (or just copy this to ~/.emacs.d/init.el) environment.etc."emacs.d/init.el".text = '' (require 'hm-init) (provide 'init) diff --git a/options/machine.nix b/options/machine.nix index bf1acd0..66f089a 100644 --- a/options/machine.nix +++ b/options/machine.nix @@ -13,14 +13,14 @@ let name = pname; value = rec { pkgwrap = mkOption { - type = types.listOf types.package; + type = with types; oneOf [ package (listOf package) ]; default = cfg.pkgsets."${pname}".pkgs; description = '' Package Wrapper for packages using a wrapper function (like python, emacs, haskell, ...) ''; }; pkgs = mkOption { - type = with types; listOf (nullOr attrs); + type = types.unspecified; default = []; description = '' ${pname} package list. @@ -37,7 +37,8 @@ in { The list of metapackages to be installed. ''; }; - pkgsets = listToAttrs (map pkgOption metapkgs); + # Package names containing '::' are sub packages and should not have their own pkgset. + pkgsets = listToAttrs (map pkgOption (lists.filter (v: !(strings.hasInfix "::" v)) metapkgs)); services = mkOption { type = types.listOf types.str; default = []; diff --git a/pkgs/pkgsets/emacs.nix b/pkgs/pkgsets/emacs.nix index 010e620..ec21711 100644 --- a/pkgs/pkgsets/emacs.nix +++ b/pkgs/pkgsets/emacs.nix @@ -4,25 +4,22 @@ with lib; let gitpkgs = import /nixpkgs {}; - modefiles = lists.forEach - (attrNames - (filterAttrs (n: v: v == "regular") - (builtins.readDir ./emacs))) - (v: "./emacs/${v}"); + fn = import (toString ../../fn.nix) { inherit lib; }; + modefiles = fn.lst { p = (toString ./emacs); b = true; }; in rec { - nixpkgs.overlays = [ - (import (builtins.fetchTarball { - url = https://github.com/nix-community/emacs-overlay/archive/master.tar.gz; - })) - ]; +# nixpkgs.overlays = [ +# (import (builtins.fetchTarball { +# url = https://github.com/nix-community/emacs-overlay/archive/master.tar.gz; +# })) +# ]; imports = [ ../../options/emacs-init.nix -# modefiles - ]; + ] ++ modefiles; programs.emacs.init = { enable = true; recommendedGcSettings = true; + prelude = '' ;; Disable UI Clutter (menu-bar-mode -1) @@ -75,7 +72,8 @@ in rec { (global-hl-line-mode t) (size-indication-mode t) (show-paren-mode t) - + (setq split-height-threshold 200) + (setq split-width-threshold nil) ;; Font Config @@ -95,6 +93,19 @@ in rec { ''; }; + + + + + + + + + + + + +### OLD STUFF # machine.pkgsets.emacs.pkgwrap = [(gitpkgs.pkgs.emacsWithPackages (ps: with ps; config.machine.pkgsets.emacs.pkgs))]; #[ # (pkgs.emacsWithPackagesFromUsePackage { diff --git a/pkgs/pkgsets/emacs/company.nix b/pkgs/pkgsets/emacs/company.nix index b00ae90..9904c04 100644 --- a/pkgs/pkgsets/emacs/company.nix +++ b/pkgs/pkgsets/emacs/company.nix @@ -1,19 +1,164 @@ -{ config, ... }: +{ config, lib, pkgs, ... }: -mkIf (elem "emacs-company" config.machine.pkgs) { - programs.emacs.init.usePackage.company = { - enable = true; - diminish = [ "company-mode" ]; - hook = [ "(after-init . global-company-mode)" ]; - bind = { "\t" = "'company-complete-common"; }; - config = '' - (setq company-idle-delay 0.3 - company-show-numbers t) - ''; - extraConfig = '' - :bind (:map company-mode-map - ([remap completion-at-point] . company-complete-common) - ([remap complete-symbol] . company-complete-common)) - ''; +with lib; + +let + # Source: https://github.com/Henry/dot-emacs/blob/master/my-lisp/company-pcomplete.el + company-pcomplete = pkgs.writeText "company-pcomplete.el" '' + ;;; company-pcomplete.el --- company-mode pcomplete backend -*- lexical-binding: t -*- + + ;; Copyright (C) 2016 Free Software Foundation, Inc. + + ;; Author: Henry G. Weller + + ;; This file is part of GNU Emacs. + + ;; GNU Emacs 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. + + ;; GNU Emacs 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 GNU Emacs. If not, see . + + + ;;; Commentary: + ;; + ;; Based on `ac-pcomplete', see https://www.emacswiki.org/emacs/EshellCompletion + ;; and `pcomplete`, see pcomplete.el. + + ;;; Code: + + (require 'company) + (require 'cl-lib) + (require 'pcomplete) + + (defgroup company-pcomplete nil + "Completion backend using pcomplete." + :group 'company) + + (defvar company-pcomplete-available 'unknown) + + (defun company-pcomplete--prefix () + (let* ((pcomplete-stub) + pcomplete-seen + pcomplete-norm-func + pcomplete-args + pcomplete-last pcomplete-index + (pcomplete-autolist pcomplete-autolist) + (pcomplete-suffix-list pcomplete-suffix-list)) + (pcomplete-completions) + (buffer-substring (pcomplete-begin) (point)))) + + (defun company-pcomplete--candidates () + (let* ((pcomplete-stub) + (pcomplete-show-list t) + pcomplete-seen pcomplete-norm-func + pcomplete-args pcomplete-last pcomplete-index + (pcomplete-autolist pcomplete-autolist) + (pcomplete-suffix-list pcomplete-suffix-list) + (candidates (pcomplete-completions)) + (prefix (buffer-substring (pcomplete-begin) (point))) + ;; Collect all possible completions for the current stub + (cnds (all-completions pcomplete-stub candidates)) + (bnds (completion-boundaries pcomplete-stub candidates nil "")) + (skip (- (length pcomplete-stub) (car bnds)))) + ;; Replace the stub at the beginning of each candidate by the prefix + (mapcar #'(lambda (cand) (concat prefix (substring cand skip))) cnds))) + + (defun company-pcomplete-available () + (when (eq company-pcomplete-available 'unknown) + (condition-case _err + (progn + (company-pcomplete--candidates) + (setq company-pcomplete-available t)) + (error + (message "Company: pcomplete not found") + (setq company-pcomplete-available nil)))) + company-pcomplete-available) + + ;;;###autoload + (defun company-pcomplete (command &optional _arg &rest ignored) + "`company-mode' completion backend using `pcomplete'." + (interactive (list 'interactive)) + (cl-case command + (interactive (company-begin-backend 'company-pcomplete)) + (prefix (when (company-pcomplete-available) + (company-pcomplete--prefix))) + (candidates (company-pcomplete--candidates)) + (sorted t))) + + (provide 'company-pcomplete) + ''; +in mkIf (elem "emacs::company" config.machine.pkgs) { + programs.emacs.init.usePackage = { + company = { + enable = true; + diminish = [ "company-mode" ]; + hook = [ "(after-init . global-company-mode)" ]; + bind = { "\t" = "'company-complete-common"; }; + init = ''(require 'ffap)''; + config = '' + ;; (setq company-tooltip-align-annotations t) + (setq company-idle-delay 0.3 + company-show-numbers t) + + ${optionalString + (elem "emacs::org" config.machine.pkgs) '' + (load-file "${company-pcomplete}")'' + } + ''; + extraConfig = '' + :bind (:map company-mode-map + ([remap completion-at-point] . company-complete-common) + ([remap complete-symbol] . company-complete-common)) + ''; + }; + company-box = { + enable = true; + hook = [ "(company-mode . (lambda () (company-box-mode)))" ]; + config = '' + (setq company-box-icons-alist 'company-box-icons-all-the-icons) + + + (setq company-box-icons-lsp + `(( 1 . ,(all-the-icons-faicon "file-text-o" :v-adjust -0.0575)) ; Text + ( 2 . ,(all-the-icons-faicon "cube" :v-adjust -0.0575)) ; Method + ( 3 . ,(all-the-icons-faicon "cube" :v-adjust -0.0575)) ; Function + ( 4 . ,(all-the-icons-faicon "cube" :v-adjust -0.0575)) ; Constructor + ( 5 . ,(all-the-icons-faicon "tag" :v-adjust -0.0575)) ; Field + ( 6 . ,(all-the-icons-faicon "tag" :v-adjust -0.0575)) ; Variable + ( 7 . ,(all-the-icons-faicon "cog" :v-adjust -0.0575)) ; Class + ( 8 . ,(all-the-icons-faicon "cogs" :v-adjust -0.0575)) ; Interface + ( 9 . ,(all-the-icons-alltheicon "less")) ; Module + (10 . ,(all-the-icons-faicon "wrench" :v-adjust -0.0575)) ; Property + (11 . ,(all-the-icons-faicon "tag" :v-adjust -0.0575)) ; Unit + (12 . ,(all-the-icons-faicon "tag" :v-adjust -0.0575)) ; Value + (13 . ,(all-the-icons-material "content_copy" :v-adjust -0.2)) ; Enum + (14 . ,(all-the-icons-faicon "tag" :v-adjust -0.0575)) ; Keyword + (15 . ,(all-the-icons-material "content_paste" :v-adjust -0.2)) ; Snippet + (16 . ,(all-the-icons-material "palette" :v-adjust -0.2)) ; Color + (17 . ,(all-the-icons-faicon "file" :v-adjust -0.0575)) ; File + (18 . ,(all-the-icons-faicon "tag" :v-adjust -0.0575)) ; Reference + (19 . ,(all-the-icons-faicon "folder" :v-adjust -0.0575)) ; Folder + (20 . ,(all-the-icons-faicon "tag" :v-adjust -0.0575)) ; EnumMember + (21 . ,(all-the-icons-faicon "tag" :v-adjust -0.0575)) ; Constant + (22 . ,(all-the-icons-faicon "cog" :v-adjust -0.0575)) ; Struct + (23 . ,(all-the-icons-faicon "bolt" :v-adjust -0.0575)) ; Event + (24 . ,(all-the-icons-faicon "tag" :v-adjust -0.0575)) ; Operator + (25 . ,(all-the-icons-faicon "cog" :v-adjust -0.0575)) ; TypeParameter + )) + ''; + }; + all-the-icons = { enable = true; }; + company-jedi = { + enable = (elem "emacs::elpy" config.machine.pkgs); + }; }; + fonts.fonts = pkgs.emacs-all-the-icons-fonts.all; } diff --git a/pkgs/pkgsets/emacs/doom-modeline.nix b/pkgs/pkgsets/emacs/doom-modeline.nix new file mode 100644 index 0000000..18c9017 --- /dev/null +++ b/pkgs/pkgsets/emacs/doom-modeline.nix @@ -0,0 +1,21 @@ +{ config, lib, pkgs, ... }: + +with lib; + +mkIf (elem "emacs::doom-modeline" config.machine.pkgs) { + programs.emacs.init.usePackage.doom-modeline = { + enable = true; + hook = [ "(after-init . doom-modeline-mode)" ]; + config = '' + (setq doom-modeline-icon t) + (setq doom-modeline-height 25) + (setq doom-modeline-bar-width 3) + ;; The default priority of detection is `ffip' > `projectile' > `project'. + (setq doom-modeline-project-detection 'project) + (setq doom-modeline-buffer-file-name-style 'truncate-upto-project) + (setq doom-modeline-unicode-fallback nil) + + (setq doom-modeline--battery-status t) +''; + }; +} diff --git a/pkgs/pkgsets/emacs/doom-themes.nix b/pkgs/pkgsets/emacs/doom-themes.nix new file mode 100644 index 0000000..a7abe73 --- /dev/null +++ b/pkgs/pkgsets/emacs/doom-themes.nix @@ -0,0 +1,16 @@ +{ config, lib, pkgs, ... }: + +with lib; + +mkIf (elem "emacs::doom-themes" config.machine.pkgs) { + programs.emacs.init.usePackage.doom-themes = { + enable = true; + config = '' + ;; Load the theme (doom-one, doom-molokai, etc); keep in mind that each theme + ;; may have their own settings. + (load-theme 'doom-solarized-dark t) + + ;; ${optionalString (elem "emacs::org" config.machine.pkgs) "(doom-themes-org-config)"} + ''; + }; +} diff --git a/pkgs/pkgsets/emacs/elpy.nix b/pkgs/pkgsets/emacs/elpy.nix new file mode 100644 index 0000000..f24e684 --- /dev/null +++ b/pkgs/pkgsets/emacs/elpy.nix @@ -0,0 +1,36 @@ +{ config, lib, ... }: + +with lib; + +mkIf (elem "emacs::elpy" config.machine.pkgs) { + programs.emacs.init.usePackage.elpy = { + enable = true; + after = [ "python" ]; + command = [ "elpy-enable" ]; + hook = [ '' + (elpy-mode + . (lambda () + (set (make-local-variable 'company-backends) + '((company-dabbrev-code company-yasnippet elpy-company-backend))))) + '' ] + ++ (optional (elem "emacs::flyspell" config.machine.pkgs) "(elpy-mode . (lambda () (flyspell-prog-mode)))") + ++ (optional (elem "emacs::flycheck" config.machine.pkgs) "(elpy-mode . (lambda () (flycheck-mode)))"); + bindLocal = { elpy-mode-map = { + "" = "company-indent-or-complete-common"; + };}; + init = ''(with-eval-after-load 'python (elpy-enable))''; + config = '' + (setq elpy-project-root-finder-functions '(elpy-project-find-git-root elpy-project-find-python-root elpy-project-find-hg-root elpy-project-find-svn-root)) + (setq elpy-rpc-backend "jedi") + (setq python-shell-interpreter "ipython" + python-shell-interpreter-args "-i --simple-prompt") + + ${optionalString (elem "emacs::flycheck" config.machine.pkgs) '' + ;; manually set what python-mypy is and configure it to ignore 3rd party imports + (setq elpy-modules (delq 'elpy-module-flymake elpy-modules)) + (setq-default flycheck-checker 'python-pylint) + (flycheck-add-next-checker 'python-pylint 'python-mypy t) + (flycheck-add-next-checker 'python-mypy 'python-flake8 t)''} + ''; + }; +} diff --git a/pkgs/pkgsets/emacs/flycheck.nix b/pkgs/pkgsets/emacs/flycheck.nix new file mode 100644 index 0000000..403749f --- /dev/null +++ b/pkgs/pkgsets/emacs/flycheck.nix @@ -0,0 +1,35 @@ +{ config, lib, ... }: + +with lib; + +mkIf (elem "emacs::flycheck" config.machine.pkgs) { + programs.emacs.init.usePackage.flycheck = { + enable = true; + command = [ "global-flycheck-mode" ]; + defer = 1; + bind = {}; + config = '' + + ''; + }; + + programs.emacs.init.usePackage.flycheck-haskell = { + enable = (elem "emacs::haskell" config.machine.pkgs); + }; + + programs.emacs.init.usePackage.flycheck-irony = { + enable = (elem "emacs::irony" config.machine.pkgs); + }; + + programs.emacs.init.usePackage.flycheck-mypy = { + enable = (elem "emacs::elpy" config.machine.pkgs); + }; + + programs.emacs.init.usePackage.pylint = { + enable = (elem "emacs::elpy" config.machine.pkgs); + }; + + programs.emacs.init.usePackage.flycheck-rust = { + enable = (elem "emacs::rust" config.machine.pkgs); + }; +} diff --git a/pkgs/pkgsets/emacs/flyspell.nix b/pkgs/pkgsets/emacs/flyspell.nix index 63f0c2d..70c1e53 100644 --- a/pkgs/pkgsets/emacs/flyspell.nix +++ b/pkgs/pkgsets/emacs/flyspell.nix @@ -1,6 +1,8 @@ -{ config, ... }: +{ config, lib, ... }: -mkIf (elem "emacs-flyspell" config.machine.pkgs) { +with lib; + +mkIf (elem "emacs::flyspell" config.machine.pkgs) { programs.emacs.init.usePackage.flyspell = { enable = true; diminish = [ "flyspell-mode" ]; diff --git a/pkgs/pkgsets/emacs/lsp.nix b/pkgs/pkgsets/emacs/lsp.nix new file mode 100644 index 0000000..42a3440 --- /dev/null +++ b/pkgs/pkgsets/emacs/lsp.nix @@ -0,0 +1,55 @@ +{ config, lib, pkgs, ... }: + +with lib; + +mkIf (elem "emacs::lsp" config.machine.pkgs) { + programs.emacs.init.usePackage = { + lsp-mode = { + enable = true; + command = [ "lsp-mode" ]; + bind = { + "C-c r r" = "lsp-rename"; + "C-c r f" = "lsp-format-buffer"; + }; + config = '' + (setq lsp-eldoc-render-all nil) + + (defvar lsp-language-id-configuration '( + ${optionalString (elem "emacs::rust" config.machine.pkgs + ''(rust-mode . "rust")'')} + )) + ''; + }; + + lsp-ui = { + enable = true; + after = [ "lsp" ]; + command = [ "lsp-ui-mode" "lsp-ui-sideline-mode" ]; + config = '' + (setq lsp-ui-sideline-enable t + lsp-ui-sideline-show-symbol nil + lsp-ui-sideline-show-hover nil + lsp-ui-sideline-show-code-actions t + lsp-ui-sideline-update-mode 'point) + ''; + }; + + lsp-ui-flycheck = { + enable = true; + after = [ "lsp-ui" ] + ++ optional (elem "emacs::flycheck" config.machine.pkgs) "flycheck"; + }; + + lsp-java = { + enable = (elem "emacs::java" config.machine.pkgs); + command = [ "lsp-java-enable" ]; + hook = [ '' + (java-mode . (lambda () + (lsp-java-enable) + (lsp-ui-sideline-mode) + (lsp-ui-flycheck-enable t) + (setq-local company-backends (list 'company-lsp)))) + '' ]; + }; + }; +} diff --git a/pkgs/pkgsets/emacs/magit.nix b/pkgs/pkgsets/emacs/magit.nix new file mode 100644 index 0000000..f8d4207 --- /dev/null +++ b/pkgs/pkgsets/emacs/magit.nix @@ -0,0 +1,12 @@ +{ config, lib, ... }: + +with lib; + +mkIf (elem "emacs::magit" config.machine.pkgs) { + programs.emacs.init.usePackage.magit = { + enable = true; + bind = { + "C-c g" = "magit-status"; + }; + }; +} diff --git a/pkgs/pkgsets/emacs/mu4e.nix b/pkgs/pkgsets/emacs/mu4e.nix index dd02185..35f73a2 100644 --- a/pkgs/pkgsets/emacs/mu4e.nix +++ b/pkgs/pkgsets/emacs/mu4e.nix @@ -2,7 +2,7 @@ with lib; -mkIf (elem "emacs-mu4e" config.machine.pkgs) { +mkIf (elem "emacs::mu4e" config.machine.pkgs) { programs.emacs.init.usePackage.mu4e = { enable = true; package = epkgs: null; @@ -47,29 +47,7 @@ mkIf (elem "emacs-mu4e" config.machine.pkgs) { (setq message-kill-buffer-on-exit t) - (setq mu4e-contexts - `(${map - (rec { name, fullName, address, sServer, sPort, sUser ? address }: '' - ,(make-mu4e-context - :name ${name} - :vars '((user-mail-address . ${address} ) - (user-full-name . ${fullName} ) - (mu4e-sent-folder . "/Sent") - (mu4e-drafts-folder . "/Drafts") - (mu4e-trash-folder . "/Deleted") - (mu4e-refile-folder . "/Archiv") - (smtpmail-smtp-user . ${sUser} ) - (smtpmail-auth-credentials . (expand-file-name "~/mail/secret/.authinfo.gpg")) - (smtpmail-default-smtp-server . ${sServer} ) - (smtpmail-smtp-server . ${sServer} ) - (smtpmail-stream-type . starttls) - (smtpmail-smtp-service . ${sPort} ) - ) - ) - ''; - ) - (import "${config.machine.secretPath}/secrets.nix").mu4e} - )) +;; mailAcc config goes here (defun my-browse-url-firefox-privately (url &optional new-window) @@ -89,10 +67,16 @@ mkIf (elem "emacs-mu4e" config.machine.pkgs) { :load-path ${pkgs.mu4e}/share/emacs/site-lisp/mu4e ''; }; + programs.emacs.init.usePackage.mu4e-alert = { enable = true; - hook = [ "'after-init-hook" = "#'mu4e-alert-enable-mode-line-display" ]; + hook = [ "'after-init-hook #'mu4e-alert-enable-mode-line-display" ]; }; + + programs.emacs.init.usePackage.org-mu4e = { + enable = (elem "emacs::org" config.machine.pkgs); + }; + environment.systemPackages = [ mu4e isync diff --git a/pkgs/pkgsets/emacs/nix-mode.nix b/pkgs/pkgsets/emacs/nix-mode.nix new file mode 100644 index 0000000..973f9ef --- /dev/null +++ b/pkgs/pkgsets/emacs/nix-mode.nix @@ -0,0 +1,10 @@ +{ config, lib, ... }: + +with lib; + +mkIf (elem "emacs::nix-mode" config.machine.pkgs) { + programs.emacs.init.usePackage.nix-mode = { + enable = true; + mode = [ ''"\\.nix\\'"'' ]; + }; +} diff --git a/pkgs/pkgsets/emacs/org.nix b/pkgs/pkgsets/emacs/org.nix new file mode 100644 index 0000000..a28610f --- /dev/null +++ b/pkgs/pkgsets/emacs/org.nix @@ -0,0 +1,419 @@ +{ config, lib, pkgs, ... }: + +with lib; + +mkIf (elem "emacs::org" config.machine.pkgs) { + programs.emacs.init.usePackage.org = { + enable = true; + package = epkgs: [ epkgs.org epkgs.org-plus-contrib ]; + mode = [ ''("\\.org\\'" . org-mode)'' ]; + command = [ "org-mode" ]; + hook = [ "(org-mode . (lambda () (org-indent-mode)))" '' + (org-mode + . (lambda () + ;; Automatic line-wrapping in org-mode + ;;(auto-fill-mode 1) + + (setq completion-at-point-functions + '(org-completion-symbols + ora-cap-filesystem)))) + '' '' + (org-mode + . (lambda () + "Beautify Org Checkbox Symbol" + (push '("[ ]" . "☐" ) prettify-symbols-alist) + (push '("[X]" . "☑" ) prettify-symbols-alist) + (push '("[-]" . "❍" ) prettify-symbols-alist) + (prettify-symbols-mode))) + '' + ] ++ optional (elem "emacs::flyspell" config.machine.pkgs) "(org-mode . (lambda () (flyspell-mode)))"; + bind = { + "C-c a" = "org-agenda"; + }; + bindLocal = { org-mode-map = { + "M-" = "org-metaup"; + "M-" = "org-metadown"; + "M-." = "org-open-at-point"; + "M-," = "org-mark-ring-goto"; + "M-S-" = "org-insert-todo-heading-respect-content"; + "M-" = "org-meta-return"; + "M-p" = "org-previous-visible-heading"; + "M-n" = "org-next-visible-heading"; + } // (optionalAttrs (elem "emacs::company" config.machine.pkgs) { + "" = "company-pcomplete"; + }); }; + config = '' + ;; Insead of "..." show "…" when there's hidden folded content + + ;; org-prettify + (defface org-checkbox-done-text + '((t (:foreground "#71696A" :strike-through t))) + "Face for the text part of a checked org-mode checkbox.") + + (font-lock-add-keywords + 'org-mode + `(("^[ \t]*\\(?:[-+*]\\|[0-9]+[).]\\)[ \t]+\\(\\(?:\\[@\\(?:start:\\)?[0-9]+\\][ \t]*\\)?\\[\\(?:X\\|\\([0-9]+\\)/\\2\\)\\][^\n]*\n\\)" + 1 'org-checkbox-done-text prepend)) + 'append) + + ;; Some characters to choose from: …, ⤵, ▼, ↴, ⬎, ⤷, and ⋱ + (setq org-ellipsis " ▼") + ;; get nice looking tables (only for non org-tables; rarely used) + (setq table-cell-horizontal-chars "\u2501") + (setq table-cell-vertical-char ?\u2503) + (setq table-cell-intersection-char ?\u254B) + + (setq org-directory "~/Documents/org/") + + ;; Show headings up to level 2 by default when opening an org files + (setq org-startup-folded 'content) + + ;; Show inline images by default + (setq org-startup-with-inline-images t) + + ;; Add more levels to headlines that get displayed with imenu + (setq org-imenu-depth 5) + + ;; Enter key follows links (= C-c C-o) + (setq org-return-follows-link t) + + ;; Don't remove links after inserting + (setq org-keep-stored-link-after-insertion t) + + (setq org-tag-alist (quote ((:startgroup) + ("WAITING" . ?w) + ("HOLD" . ?h) + ("CANCELLED" . ?c) + ("NOTE" . ?n) + (:endgroup) + ("PERSONAL" . ?P) + ("WORK" . ?W) + ("ATOMX" . ?A) + ("E5" . ?E) + ("HOGASO" . ?H) + ("ORG" . ?o) + ("crypt" . ?C) + ("FLAGGED" . ??)))) + + ;; Allow setting single tags without the menu + (setq org-fast-tag-selection-single-key (quote expert)) + + (setq org-archive-mark-done nil) + (setq org-archive-location "%s_archive::* Archived Tasks") + + ;; C-RET, C-S-RET insert new heading after current task content + (setq org-insert-heading-respect-content nil) + + ;; Show a little bit more when using sparse-trees + (setq org-show-following-heading t) + (setq org-show-hierarchy-above t) + (setq org-show-siblings (quote ((default)))) + + ;; don't show * / = etc + (setq org-hide-emphasis-markers t) + + ;; leave highlights in sparse tree after edit. C-c C-c removes highlights + (setq org-remove-highlights-with-change nil) + + ;; M-RET should not split the lines + (setq org-M-RET-may-split-line '((default . nil))) + + (setq org-special-ctrl-a/e t) + (setq org-special-ctrl-k t) + (setq org-yank-adjusted-subtrees t) + + ;; Show org entities as UTF-8 characters (e.g. \sum as ∑) + (setq org-pretty-entities t) + ;; But Don't print "bar" as subscript in "foo_bar" + (setq org-pretty-entities-include-sub-superscripts nil) + ;; And also don't display ^ or _ as super/subscripts + (setq org-use-sub-superscripts nil) + ;; undone TODO entries will block switching the parent to DONE + (setq org-enforce-todo-dependencies t) + + (setq org-use-fast-todo-selection t) + + (setq org-todo-keywords + (quote ((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d)") + (sequence "WAITING(w@/!)" "HOLD(h@/!)" "|" "CANCELLED(c@/!)" "PHONE" "MEETING")))) + + (setq org-todo-keyword-faces + (quote (("TODO" :foreground "red" :weight bold) + ("NEXT" :foreground "blue" :weight bold) + ("DONE" :foreground "forest green" :weight bold) + ("WAITING" :foreground "orange" :weight bold) + ("HOLD" :foreground "magenta" :weight bold) + ("CANCELLED" :foreground "forest green" :weight bold) + ("MEETING" :foreground "forest green" :weight bold) + ("PHONE" :foreground "forest green" :weight bold)))) + + ;; Auto completion for symbols in org-mode + ;; https://oremacs.com/2017/10/04/completion-at-point/ + (defun org-completion-symbols () + (when (looking-back "[`~=][a-zA-Z]+" nil) + (let (cands) + (save-match-data + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "[`~=]\\([a-zA-Z.\\-_]+\\)[`~=]" nil t) + (cl-pushnew + (match-string-no-properties 0) cands :test 'equal)) + cands)) + (when cands + (list (match-beginning 0) (match-end 0) cands))))) + +(defun ora-cap-filesystem () + (let (path) + (when (setq path (ffap-string-at-point)) + (when (string-match "\\`file:\\(.*\\)\\'" path) + (setq path (match-string 1 path))) + (let ((compl (all-completions path #'read-file-name-internal))) + (when compl + (let* ((str (car compl)) + (offset + (let ((i 0) + (len (length str))) + (while (and (< i len) + (equal (get-text-property i 'face str) + 'completions-common-part)) + (cl-incf i)) + i))) + (list (- (point) offset) (point) compl))))))) + + ''; + }; + + programs.emacs.init.usePackage.ob = { + enable = true; + defer = true; + init = '' + (add-hook 'org-babel-after-execute-hook 'org-display-inline-images 'append) + ''; + config = '' + (setq org-confirm-babel-evaluate nil) ; don't prompt me to confirm everytime I want to evaluate a block + + (defun org-babel-restart-session-to-point (&optional arg) + "Restart session up to the src-block in the current point. + Goes to beginning of buffer and executes each code block with + `org-babel-execute-src-block' that has the same language and + session as the current block. ARG has same meaning as in + `org-babel-execute-src-block'." + (interactive "P") + (unless (org-in-src-block-p) + (error "You must be in a src-block to run this command")) + (let* ((current-point (point-marker)) + (info (org-babel-get-src-block-info)) + (lang (nth 0 info)) + (params (nth 2 info)) + (session (cdr (assoc :session params)))) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward org-babel-src-block-regexp nil t) + ;; goto start of block + (goto-char (match-beginning 0)) + (let* ((this-info (org-babel-get-src-block-info)) + (this-lang (nth 0 this-info)) + (this-params (nth 2 this-info)) + (this-session (cdr (assoc :session this-params)))) + (when + (and + (< (point) (marker-position current-point)) + (string= lang this-lang) + (src-block-in-session-p session)) + (org-babel-execute-src-block arg))) + ;; move forward so we can find the next block + (forward-line))))) + + (defun org-babel-kill-session () + "Kill session for current code block." + (interactive) + (unless (org-in-src-block-p) + (error "You must be in a src-block to run this command")) + (save-window-excursion + (org-babel-switch-to-session) + (kill-buffer))) + + (defun org-babel-remove-result-buffer () + "Remove results from every code block in buffer." + (interactive) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward org-babel-src-block-regexp nil t) + (org-babel-remove-result)))) + + + ;; this adds a "new language" in babel that gets exported as js in html + ;; https://www.reddit.com/r/orgmode/comments/5bi6ku/tip_for_exporting_javascript_source_block_to/ + (add-to-list 'org-src-lang-modes '("inline-js" . javascript)) + (defvar org-babel-default-header-args:inline-js + '((:results . "html") + (:exports . "results"))) + (defun org-babel-execute:inline-js (body _params) + (format "" body)) + + ;; Path when plantuml is installed from AUR (package `plantuml') + (setq org-plantuml-jar-path "/opt/plantuml/plantuml.jar") + + ;; add all languages to org mode + (org-babel-do-load-languages + 'org-babel-load-languages + '((C . t) + ;;(R . t) + (asymptote) + (awk) + (calc . t) + (clojure . t) + (comint) + (css) + (ditaa . t) + (dot . t) + (emacs-lisp . t) + (fortran) + (gnuplot . t) + (haskell) + (io) + (java) + (js . t) + (latex) + (ledger . t) + (lilypond) + (lisp) + (lua . t) + (matlab) + (maxima) + (mscgen) + (ocaml) + (octave . t) + (org . t) + (perl) + (picolisp) + (plantuml . t) + (python . t) + ;; (ipython . t) + ;; (restclient . t) + (ref) + (ruby) + (sass) + (scala) + (scheme) + (screen) + (shell . t) + (shen) + (snippet) + (sql . t) + (sqlite . t))) + ''; + }; + + programs.emacs.init.usePackage.org-src = { + enable = true; + defer = true; + init = ''(put 'org-src-preserve-indentation 'safe-local-variable 'booleanp)''; + config = '' + (setq org-src-window-setup 'current-window) + + (setq org-src-fontify-natively t) ; syntax highlighting for source code blocks + + ;; Tab should do indent in code blocks + ;; I think I hate this function (causes scroll on TAB + (setq org-src-tab-acts-natively t) + ;; ?Fix weird scrolling + + ;; Don't remove (or add) any extra whitespace + (setq org-src-preserve-indentation nil) + (setq org-edit-src-content-indentation 0) + + ;;; Some helper function to manage org-babel sessions + + (defun src-block-in-session-p (&optional name) + "Return if src-block is in a session of NAME. + NAME may be nil for unnamed sessions." + (let* ((info (org-babel-get-src-block-info)) + ;;(lang (nth 0 info)) + ;;(body (nth 1 info)) + (params (nth 2 info)) + (session (cdr (assoc :session params)))) + + (cond + ;; unnamed session, both name and session are nil + ((and (null session) + (null name)) + t) + ;; Matching name and session + ((and + (stringp name) + (stringp session) + (string= name session)) + t) + ;; no match + (t nil)))) + + ;; dot == graphviz-dot + (add-to-list 'org-src-lang-modes '("dot" . graphviz-dot)) + + ;; Add 'conf-mode' to org-babel + (add-to-list 'org-src-lang-modes '("ini" . conf)) + (add-to-list 'org-src-lang-modes '("conf" . conf)) + ''; + }; + + programs.emacs.init.usePackage.org-tempo = { + enable = true; + }; + + programs.emacs.init.usePackage.ox = { + enable = true; + defer = true; + command = []; + config = '' + ;; Use html5 as org export and use new tags + (setq org-html-doctype "html5") + (setq org-html-html5-fancy t) + ;; Don't add html footer to export + (setq org-html-postamble nil) + ;; Don't export ^ or _ as super/subscripts + (setq org-export-with-sub-superscripts nil) + ''; + }; + + programs.emacs.init.usePackage.ox-gfm = { + enable = true; + after = [ "ox" ]; + }; + + programs.emacs.init.usePackage.ox-rst = { + enable = true; + after = [ "ox" ]; + }; + + programs.emacs.init.usePackage.ox-md = { + enable = true; + after = [ "ox" ]; + }; + + programs.emacs.init.usePackage.org-bullets = { + enable = true; + hook = [ "(org-mode . org-bullets-mode)" ]; + }; + + programs.emacs.init.usePackage.org-crypt = { + enable = true; + after = [ "org" ]; + bindLocal = { org-mode-map = { + "C-c d" = "org-decrypt-entry"; + "C-c e" = "org-encrypt-entry"; + };}; + config = '' + (org-crypt-use-before-save-magic) + (setq org-tags-exclude-from-inheritance (quote ("crypt"))) + ;; GPG key to use for encryption + (setq org-crypt-key "BD9667B90757EAE9CDFE510A59A28744FE81FFEB") + ;; don't ask to disable auto-save + (setq org-crypt-disable-auto-save nil) + ''; + }; + + programs.emacs.init.usePackage.org-drill = { + enable = true; + }; +} diff --git a/pkgs/pkgsets/emacs/powerline.nix b/pkgs/pkgsets/emacs/powerline.nix index 57c4f7c..56bdec2 100644 --- a/pkgs/pkgsets/emacs/powerline.nix +++ b/pkgs/pkgsets/emacs/powerline.nix @@ -1,7 +1,9 @@ -{ config, ... }: +{ config, lib, ... }: -mkIf (elem "emacs-poerline" config.machine.pkgs) { - programs.emacs.init.usePackage.solarized-theme = { +with lib; + +mkIf (elem "emacs::powerline" config.machine.pkgs) { + programs.emacs.init.usePackage.powerline = { enable = true; config = '' ;; color palette from https://github.com/kuanyui/moe-theme.el/blob/master/moe-theme.el#L283 diff --git a/pkgs/pkgsets/emacs/rust.nix b/pkgs/pkgsets/emacs/rust.nix new file mode 100644 index 0000000..b33b9fd --- /dev/null +++ b/pkgs/pkgsets/emacs/rust.nix @@ -0,0 +1,39 @@ +{ config, lib, pkgs, ... }: + +with lib; + +mkIf (elem "emacs::rust" config.machine.pkgs) { + programs.emacs.init.usePackage.rust-mode = { + enable = true; + hook = [ ''(rust-mode . (lambda () (racer-mode)))'' ]; + mode = [ ''("\\.rs\\'" . rust-mode)'' ]; + command = [ "rust-mode" ]; + config = '' + (setq rust-rustfmt-bin "${pkgs.rustfmt}/bin/rustfmt") + (setq rust-format-on-save t) + ''; + }; + + programs.emacs.init.usePackage.cargo = { + enable = true; + defer = true; + # hook = [ ''ru]; + }; + + programs.emacs.init.usePackage.racer = { + enable = true; + defer = true; + bindLocal = optionalAttrs (elem "emacs::company" config.machine.pkgs) { rust-mode-map = { + "" = "company-indent-or-complete-common"; + };}; + hook = [ + ''(racer-mode . (lambda () (eldoc-mode)))'' + ] ++ optional (elem "emacs::company" config.machine.pkgs) ''(racer-mode . (lambda () (company-mode)))''; + + config = '' + (setq racer-rust-src-path (concat (getenv "HOME") + "/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/")) + (setq racer-cmd "${pkgs.rustracer}/bin/racer") + ''; + }; +} diff --git a/pkgs/pkgsets/emacs/solarized-theme.nix b/pkgs/pkgsets/emacs/solarized-theme.nix index a1e0265..5ba5249 100644 --- a/pkgs/pkgsets/emacs/solarized-theme.nix +++ b/pkgs/pkgsets/emacs/solarized-theme.nix @@ -1,6 +1,8 @@ -{ config, ... }: +{ config, lib, ... }: -mkIf (elem "emacs-solarized-theme" config.machine.pkgs) { +with lib; + +mkIf (elem "emacs::solarized-theme" config.machine.pkgs) { programs.emacs.init.usePackage.solarized-theme = { enable = true; config = "(load-theme 'solarized-dark t)"; diff --git a/pkgs/systemPackages.nix b/pkgs/systemPackages.nix index 0c51c08..0930b4f 100644 --- a/pkgs/systemPackages.nix +++ b/pkgs/systemPackages.nix @@ -4,20 +4,23 @@ with lib; let cfg = config.machine; - pkgsets = (lists.forEach - (attrNames (filterAttrs (n: v: v == "regular") (builtins.readDir (toString ./pkgsets)))) - (v: (./. + "/pkgsets/${v}"))); + fn = import (toString ../fn.nix) { inherit lib; }; + pkgsets = map (v: (toString ./.) + "/pkgsets/${v}") (fn.lsf (toString ./pkgsets)); in { imports = pkgsets; - environment.systemPackages = flatten (lists.forEach - (attrVals cfg.pkgs cfg.pkgsets) - (v: v.pkgwrap)); + environment.systemPackages = flatten + (lists.forEach + (attrVals + (filter + (v: !(strings.hasInfix "::" v)) cfg.pkgs) + cfg.pkgsets) + (v: v.pkgwrap)); - # services.emacs = mkIf (elem "emacs" cfg.pkgs) { - # defaultEditor = true; - # enable = true; - # install = true; - # package = (elemAt cfg.pkgsets.emacs.pkgwrap 0); - # }; + services.emacs = mkIf (elem "emacs" cfg.pkgs) { + defaultEditor = true; + enable = true; + install = true; + package = cfg.pkgsets.emacs.pkgwrap; + }; }