]> git.eshelyaron.com Git - dotfiles.git/commitdiff
Initial commit
authorEshel Yaron <eshel@areionsec.com>
Fri, 1 Apr 2022 07:49:32 +0000 (10:49 +0300)
committerEshel Yaron <eshel@areionsec.com>
Fri, 1 Apr 2022 07:49:32 +0000 (10:49 +0300)
41 files changed:
.emacs.d/checkouts/flymake-swi-prolog [new submodule]
.emacs.d/etc/custom.el [new file with mode: 0644]
.emacs.d/init.el [new file with mode: 0644]
.emacs.d/lisp/aide.el [new file with mode: 0644]
.emacs.d/lisp/dap-swi-prolog.el [new file with mode: 0644]
.emacs.d/lisp/init-benchmarking.el [new file with mode: 0644]
.emacs.d/lisp/init-company.el [new file with mode: 0644]
.emacs.d/lisp/init-compile.el [new file with mode: 0644]
.emacs.d/lisp/init-editing-utils.el [new file with mode: 0644]
.emacs.d/lisp/init-elpa.el [new file with mode: 0644]
.emacs.d/lisp/init-exec-path.el [new file with mode: 0644]
.emacs.d/lisp/init-git.el [new file with mode: 0644]
.emacs.d/lisp/init-github.el [new file with mode: 0644]
.emacs.d/lisp/init-go.el [new file with mode: 0644]
.emacs.d/lisp/init-grep.el [new file with mode: 0644]
.emacs.d/lisp/init-gui-frames.el [new file with mode: 0644]
.emacs.d/lisp/init-helpful.el [new file with mode: 0644]
.emacs.d/lisp/init-hippie-expand.el [new file with mode: 0644]
.emacs.d/lisp/init-ialign.el [new file with mode: 0644]
.emacs.d/lisp/init-ibuffer.el [new file with mode: 0644]
.emacs.d/lisp/init-idris2.el [new file with mode: 0644]
.emacs.d/lisp/init-isearch.el [new file with mode: 0644]
.emacs.d/lisp/init-keyfreq.el [new file with mode: 0644]
.emacs.d/lisp/init-minibuffer.el [new file with mode: 0644]
.emacs.d/lisp/init-pdf.el [new file with mode: 0644]
.emacs.d/lisp/init-projectile.el [new file with mode: 0644]
.emacs.d/lisp/init-prolog.el [new file with mode: 0644]
.emacs.d/lisp/init-recentf.el [new file with mode: 0644]
.emacs.d/lisp/init-site-lisp.el [new file with mode: 0644]
.emacs.d/lisp/init-themes.el [new file with mode: 0644]
.emacs.d/lisp/init-utils.el [new file with mode: 0644]
.emacs.d/lisp/init-vc.el [new file with mode: 0644]
.emacs.d/lisp/init-web.el [new file with mode: 0644]
.emacs.d/lisp/init-web.pl [new file with mode: 0644]
.emacs.d/lisp/init-whitespace.el [new file with mode: 0644]
.emacs.d/lisp/init-windows.el [new file with mode: 0644]
.emacs.d/lisp/init-yassnippet.el [new file with mode: 0644]
.emacs.d/lisp/profile-dotemacs.el [new file with mode: 0644]
.emacs.d/lisp/publish.el [new file with mode: 0644]
.gitignore [new file with mode: 0644]
.gitmodules [new file with mode: 0644]

diff --git a/.emacs.d/checkouts/flymake-swi-prolog b/.emacs.d/checkouts/flymake-swi-prolog
new file mode 160000 (submodule)
index 0000000..9407a57
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit 9407a57779933c4745fbace18a64be12a120a547
diff --git a/.emacs.d/etc/custom.el b/.emacs.d/etc/custom.el
new file mode 100644 (file)
index 0000000..6153bf0
--- /dev/null
@@ -0,0 +1,38 @@
+(custom-set-variables
+ ;; custom-set-variables was added by Custom.
+ ;; If you edit it by hand, you could mess it up, so be careful.
+ ;; Your init file should contain only one such instance.
+ ;; If there is more than one, they won't work right.
+ '(comint-process-echoes t)
+ '(company-minimum-prefix-length 2)
+ '(dap-internal-terminal 'dap-internal-terminal-shell)
+ '(dap-print-io t)
+ '(dap-ui-repl-prompt "?- ")
+ '(enable-recursive-minibuffers t)
+ '(flymake-proc-allowed-file-name-masks
+   '(("\\.\\(?:c\\(?:pp\\|xx\\|\\+\\+\\)?\\|CC\\)\\'" flymake-proc-simple-make-init nil flymake-proc-real-file-name-considering-includes)
+     ("\\.xml\\'" flymake-proc-xml-init nil nil)
+     ("\\.html?\\'" flymake-proc-xml-init nil nil)
+     ("\\.cs\\'" flymake-proc-simple-make-init nil nil)
+     ("\\.php[345]?\\'" flymake-proc-php-init nil nil)
+     ("\\.h\\'" flymake-proc-master-make-header-init flymake-proc-master-cleanup nil)
+     ("\\.java\\'" flymake-proc-simple-make-java-init flymake-proc-simple-java-cleanup nil)
+     ("[0-9]+\\.tex\\'" flymake-proc-master-tex-init flymake-proc-master-cleanup nil)
+     ("\\.tex\\'" flymake-proc-simple-tex-init nil nil)
+     ("\\.idl\\'" flymake-proc-simple-make-init nil nil)))
+ '(max-specpdl-size 10000)
+ '(mct-apply-completion-stripes t)
+ '(mct-hide-completion-mode-line t)
+ '(mct-live-update-delay 0.6)
+ '(org-agenda-files '("~/inbox.org"))
+ '(org-agenda-start-on-weekday 0)
+ '(org-default-notes-file "~/inbox.org")
+ '(package-selected-packages
+   '(cape corfu speed-type json-mode json-navigator flymake-swi-prolog package-lint package-lint-flymake all-the-icons-completion mct dap-ui auto-package-update zenburn-theme yasnippet-snippets yaml-mode yagist windswap whole-line-or-region whitespace-cleanup-mode which-key w3m vterm vlf vertico use-package unfill tramp terraform-mode terraform-doc symbol-overlay switch-window smartparens sketch-mode semi rustic rg reformatter rainbow-delimiters protobuf-mode proof-general pdf-tools page-break-lines org-superstar orderless ob-prolog ns-auto-titlebar no-littering multiple-cursors move-dup mode-line-bell markdown-toc markdown-changelog marginalia magit-todos lsp-ui lsp-java lsp-haskell lorem-ipsum list-unicode-display keyfreq keycast iedit idris-mode ibuffer-vc ibuffer-projectile ialign htmlize highlight-escape-sequences helpful graphviz-dot-mode go-mode gnu-elpa-keyring-update gitignore-mode github-review github-clone gitconfig-mode git-timemachine git-blamed ggtags fullframe forge flycheck-golangci-lint expand-region exec-path-from-shell esup erlang epresent embark-consult emacsql-sqlite3 elixir-mode ediprolog dtache dockerfile-mode disable-mouse diminish diff-hl define-word default-text-scale consult-flycheck company-quickhelp company-coq company-auctex command-log-mode bug-reference-github browse-kill-ring browse-at-remote beacon auctex-latexmk anzu all-the-icons alert affe ace-jump-mode academic-phrases))
+ '(savehist-additional-variables '(esy/org-capture-to-project-heading-history-list)))
+(custom-set-faces
+ ;; custom-set-faces was added by Custom.
+ ;; If you edit it by hand, you could mess it up, so be careful.
+ ;; Your init file should contain only one such instance.
+ ;; If there is more than one, they won't work right.
+ '(aw-leading-char-face ((t (:inherit (bold modus-themes-reset-soft) :foreground "#fe6060" :height 1)))))
diff --git a/.emacs.d/init.el b/.emacs.d/init.el
new file mode 100644 (file)
index 0000000..6026b60
--- /dev/null
@@ -0,0 +1,323 @@
+;;; init.el --- Load the full configuration -*- lexical-binding: t -*-
+;;; Commentary:
+
+;;; Code:
+
+;; Produce backtraces when errors occur: can be helpful to diagnose startup issues
+;;(setq debug-on-error t)
+
+
+(let ((normal-gc-cons-threshold (* 20 1024 1024))
+      (init-gc-cons-threshold (* 128 1024 1024)))
+  (setq gc-cons-threshold init-gc-cons-threshold)
+  (add-hook 'emacs-startup-hook
+            (lambda () (setq gc-cons-threshold normal-gc-cons-threshold))))
+
+(require 'package)
+
+(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/"))
+
+(package-initialize)
+
+(unless (package-installed-p 'use-package)
+  ((package-refresh-contents)
+   (package-install 'use-package)))
+
+(global-set-key (kbd "C-s-f") 'toggle-frame-fullscreen)
+
+(require 'use-package)
+
+(setq use-package-always-ensure t)
+
+(setq-default indent-tabs-mode nil)
+
+(use-package auto-package-update
+  :custom
+  (auto-package-update-interval 7)
+  (auto-package-update-prompt-before-update t)
+  (auto-package-update-hide-results t)
+  :config
+  (auto-package-update-maybe)
+  (auto-package-update-at-time "09:00"))
+
+(use-package no-littering)
+
+(setq auto-save-file-name-transforms
+      `((".*" ,(no-littering-expand-var-file-name "auto-save/") t)))
+
+(setq custom-file (no-littering-expand-etc-file-name "custom.el"))
+(load custom-file 'noerror 'nomessage)
+
+ (when (fboundp 'startup-redirect-eln-cache)
+   (startup-redirect-eln-cache
+    (convert-standard-filename
+     (expand-file-name  "var/eln-cache/" user-emacs-directory))))
+
+(load-theme 'modus-vivendi)
+(modus-themes-load-vivendi)
+
+(add-to-list 'load-path (expand-file-name "lisp" user-emacs-directory))
+
+(recentf-mode 1)
+
+(setq history-length 25)
+(savehist-mode 1)
+
+(save-place-mode 1)
+
+(add-hook 'after-init-hook 'exec-path-from-shell-initialize)
+
+(setq use-file-dialog nil)
+(setq use-dialog-box nil)
+(setq inhibit-startup-screen t)
+
+(menu-bar-mode -1)
+(tool-bar-mode -1)
+(set-scroll-bar-mode nil)
+(setq ns-use-native-fullscreen t)
+
+
+(require 'wgrep)
+(require 'transient)
+(require 'rg)
+(rg-enable-default-bindings)
+
+
+(add-hook 'after-init-hook 'global-auto-revert-mode)
+(setq global-auto-revert-non-file-buffers t
+      auto-revert-verbose nil)
+
+(add-hook 'after-init-hook 'transient-mark-mode)
+
+(add-hook 'prog-mode-hook 'rainbow-delimiters-mode)
+(add-hook 'prog-mode-hook 'display-line-numbers-mode)
+
+(add-hook 'after-init-hook 'show-paren-mode)
+
+(require 'symbol-overlay)
+(global-set-key (kbd "M-i") 'symbol-overlay-put)
+
+
+(use-package move-dup
+  :bind (("M-p" . move-dup-move-lines-up)
+         ("M-n" . move-dup-move-lines-down)
+         ("s-p" . move-dup-duplicate-up)
+         ("s-n" . move-dup-duplicate-down)))
+
+(require 'which-key)
+(add-hook 'after-init-hook 'which-key-mode)
+
+(require 'whitespace-cleanup-mode)
+(add-hook 'after-init-hook 'global-whitespace-cleanup-mode)
+
+(global-set-key [remap just-one-space] 'cycle-spacing)
+
+(require 'diff-hl)
+(add-hook 'after-init-hook 'global-diff-hl-mode)
+
+(use-package magit
+  :bind (("C-x g" . magit-status))
+  :init
+  (add-hook 'magit-post-refresh-hook #'diff-hl-magit-post-refresh))
+
+
+(require 'forge)
+
+(require 'pdf-tools)
+(add-hook 'pdf-view-mode-hook 'pdf-tools-install)
+
+(require 'ialign)
+
+(global-set-key (kbd "C-x l") #'ialign)
+
+(global-set-key (kbd "C-x m") #'execute-extended-command)  ; bound to #'compose-mail by default
+
+(require 'keycast)
+
+(require 'publish)
+
+
+(use-package dtache
+  :custom (dtache-notification-function #'dtache-state-transitionion-echo-message)
+  :init (dtache-setup)
+  :bind (([remap async-shell-command] . dtache-shell-command)))
+
+(add-to-list 'auto-mode-alist '("\\.pl\\'" . prolog-mode))
+(add-to-list 'auto-mode-alist '("\\.plt\\'" . prolog-mode))
+
+(define-derived-mode dapscript-mode
+  prolog-mode "DAP script"
+  "Major mode for dapscript source files."
+  (flymake-mode))
+
+(add-to-list 'auto-mode-alist '("\\.dapscript\\'" . dapscript-mode))
+
+(use-package vterm)
+(use-package lsp-mode)
+(use-package lsp-ui)
+(use-package dap-mode)
+
+(global-set-key (kbd "C-c d") 'dap-hydra)
+
+(require 'dap-ui)
+(require 'dap-swi-prolog)
+
+(require 'helpful)
+(global-set-key (kbd "C-h f") #'helpful-callable)
+(global-set-key (kbd "C-h v") #'helpful-variable)
+(global-set-key (kbd "C-h k") #'helpful-key)
+
+
+(use-package corfu
+  :custom
+  (corfu-cycle t)
+  (corfu-auto t)
+  :init
+  (corfu-global-mode))
+
+(use-package dabbrev
+  :bind (("M-/" . dabbrev-completion)
+         ("C-M-/" . dabbrev-expand)))
+
+(use-package cape
+  :init
+  (add-to-list 'completion-at-point-functions #'cape-file)
+  (add-to-list 'completion-at-point-functions #'cape-dabbrev))
+
+(use-package reformatter)
+
+(setq read-extended-command-predicate 'command-completion-default-include-p)
+(use-package mct)
+(add-hook 'after-init-hook 'mct-minibuffer-mode)
+
+(defun esy/choose-completion-no-exit ()
+  "Hack to circumvent 'mct-choose-completion-no-exit' leaving the minibuffer."
+  (interactive)
+  (mct-choose-completion-no-exit)
+  (mct-focus-minibuffer))
+
+(defun esy/edit-completion ()
+  "Hack to circumvent 'mct-edit-completion' leaving the minibuffer."
+  (interactive)
+  (mct-edit-completion)
+  (mct-focus-minibuffer))
+
+(define-key mct-minibuffer-completion-list-map [remap mct-choose-completion-no-exit] #'esy/choose-completion-no-exit)
+(define-key mct-minibuffer-completion-list-map [remap mct-edit-completion] #'esy/edit-completion)
+
+(use-package marginalia
+  :init
+  (marginalia-mode))
+
+(use-package orderless
+  :custom (completion-styles '(orderless)))
+
+(use-package all-the-icons
+  :if (display-graphic-p))
+
+(use-package all-the-icons-completion
+  :config (all-the-icons-completion-mode))
+
+(add-hook 'marginalia-mode-hook #'all-the-icons-completion-marginalia-setup)
+
+(add-hook 'prog-mode-hook 'flymake-mode)
+
+(require 'consult)
+(require 'consult-imenu)
+
+(global-set-key [remap switch-to-buffer] 'consult-buffer)
+(global-set-key [remap switch-to-buffer-other-window] 'consult-buffer-other-window)
+(global-set-key [remap switch-to-buffer-other-frame] 'consult-buffer-other-frame)
+(global-set-key [remap goto-line] 'consult-goto-line)
+
+(global-set-key (kbd "C-c !") 'consult-flymake)
+
+(defvar esy/inbox-path "~/inbox.org"
+  "Path to my Org mode inbox file.")
+
+(defvar esy/org-capture-to-project-heading-history-list nil
+  "History list for 'esy/org-capture-to-project-heading'.")
+
+(setq savehist-additional-variables (list 'esy/org-capture-to-project-heading-history-list))
+
+(defun esy/org-capture-to-project-heading ()
+  "Prompt for a projects and capture a related task."
+  (let* ((projects
+          (org-map-entries `(lambda () (nth 4 (org-heading-components)))
+                           "+project+LEVEL=2" (list esy/inbox-path)))
+         (choice (completing-read "Project: " projects nil t nil 'esy/org-capture-to-project-heading-history-list)))
+    (org-capture-set-target-location (list 'file+olp esy/inbox-path "Projects" choice))))
+
+
+(setq org-capture-templates '(("t" "Todo [inbox]" entry
+                               (file+headline esy/inbox-path "Tasks")
+                               "** TODO %?    %^g\n %i\n %t\n %a\n" :prepend t)
+                              ("n" "New Project" entry
+                               (file+headline esy/inbox-path "Projects")
+                               "** %?    %^g\n %i\n" :prepend t)
+                              ("p" "New Project Task" entry
+                               (file+function esy/inbox-path esy/org-capture-to-project-heading)
+                               "*** TODO %?\n:PROPERTIES:\n:CreatedAt: %t\n:CapturedAt: %a\n:END:\n%i\n" :prepend t)))
+
+(global-set-key (kbd "C-c c") 'org-capture)
+
+
+(use-package org-superstar)
+(add-hook 'org-mode-hook #'org-superstar-mode)
+
+(use-package embark
+  :bind
+  (("C-." . embark-act))
+  :config
+  ;; Hide the mode line of the Embark live/completions buffers
+  (add-to-list 'display-buffer-alist
+               '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
+                 nil
+                 (window-parameters (mode-line-format . none)))))
+
+;; Consult users will also want the embark-consult package.
+(use-package embark-consult
+  :ensure t
+  :after (embark consult)
+  :demand t ; only necessary if you have the hook below
+  :hook
+  (embark-collect-mode . consult-preview-at-point-mode))
+
+(require 'windmove)
+(windmove-default-keybindings 'meta)
+
+(use-package ace-window
+  :bind
+  (("C-x o" . ace-window))
+  :config
+  (setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l)))
+
+(require 'beacon)
+(beacon-mode 1)
+(setq beacon-color "magenta")
+
+(setq ring-bell-function 'ignore)
+
+(defun esy/pin-buffer ()
+  "Pin buffer to current window."
+  (interactive)
+  (message
+   (if (let (window (get-buffer-window (current-buffer)))
+         (set-window-dedicated-p window (not (window-dedicated-p window))))
+       "pinned buffer" "un-pinned buffer")
+   ))
+
+(require 'company)
+
+(add-to-list 'load-path "~/.emacs.d/checkouts/flymake-swi-prolog")
+
+(require 'flymake-swi-prolog)
+
+(add-hook 'prolog-mode-hook #'flymake-swi-prolog-setup-backend)
+
+(add-to-list 'auto-mode-alist '("\\.json\\'" . json-mode))
+
+(global-set-key [remap transpose-chars] #'backward-kill-word)
+
+(provide 'init)
+;;; init.el ends here
diff --git a/.emacs.d/lisp/aide.el b/.emacs.d/lisp/aide.el
new file mode 100644 (file)
index 0000000..4d3fd06
--- /dev/null
@@ -0,0 +1,199 @@
+;;; aide.el --- An Emacs front end for GPT APIs like OpenAI  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021  Junji Zhi
+
+;; Author: Junji Zhi
+;; Keywords: gpt-3 openai
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Simple wrapper to call GPT APIs
+;;
+;; For details, please see http://github.com/junjizhi/aide.el
+
+;;; Code:
+
+(require 'request)
+
+(defgroup aide nil
+  "aide.el custom settings"
+  :group 'external
+  :prefix "aide-")
+
+(defcustom aide-max-tokens 100
+  "The max-tokens paramater that aide.el sends to OpenAI API."
+  :type 'integer
+  :group 'aide)
+
+(defcustom aide-temperature 0
+  "The temperature paramater that aide.el sends to OpenAI API."
+  :type 'float
+  :group 'aide)
+
+(defcustom aide-top-p 0.1
+  "The top-p paramater that aide.el sends to OpenAI API."
+  :type 'float
+  :group 'aide)
+
+(defcustom aide-frequency-penalty 0
+  "The frequency_penalty paramater that aide.el sends to OpenAI API."
+  :type 'float
+  :group 'aide)
+
+(defcustom aide-presence-penalty 0
+  "The presence_penalty paramater that aide.el sends to OpenAI API."
+  :type 'float
+  :group 'aide)
+
+
+(defun aide-openai-complete (api-key prompt)
+  "Return the prompt answer from OpenAI API.
+API-KEY is the OpenAI API key.
+PROMPT is the prompt string we send to the API."
+  (let ((result nil)
+        (auth-value (format "Bearer %s" api-key)))
+    (request
+      "https://api.openai.com/v1/engines/davinci/completions"
+      :type "POST"
+      :data (json-encode `(("prompt" . ,prompt)
+                           ("max_tokens" . ,aide-max-tokens)
+                           ("temperature" . ,aide-temperature)
+                           ("frequency_penalty" . ,aide-frequency-penalty)
+                           ("presence_penalty" . ,aide-presence-penalty)
+                           ("top_p" . ,aide-top-p)))
+      :headers `(("Authorization" . ,auth-value) ("Content-Type" . "application/json"))
+      :sync t
+      :parser 'json-read
+      :success (cl-function
+                (lambda (&key data &allow-other-keys)
+                  (setq result (alist-get 'text (elt (alist-get 'choices data) 0))))))
+    result))
+
+(defun aide-openai-complete-region (start end)
+  "Send the region to OpenAI autocomplete engine and get the result.
+START and END are selected region boundaries."
+  (interactive "r")
+  (let* ((region (buffer-substring-no-properties start end))
+         (result (aide--openai-complete-string region)))
+    (message "%s" result)))
+
+(defun aide-openai-complete-region-insert (start end)
+  "Send the region to OpenAI and insert the result to the end of buffer.
+START and END are selected region boundaries."
+  (interactive "r")
+  (let* ((region (buffer-substring-no-properties start end))
+         (result (aide--openai-complete-string region))
+        original-point)
+    (goto-char (point-max))
+    (setq original-point (point))
+    (if result
+        (progn
+          (insert "\n" result)
+          (fill-paragraph)
+          (let ((x (make-overlay original-point (point-max))))
+            (overlay-put x 'face '(:foreground "orange red")))
+          result)
+      (message "Empty result"))))
+
+(defun aide-openai-complete-buffer-insert ()
+  "Send the ENTIRE buffer to OpenAI and insert the result to the end of buffer."
+  (interactive)
+  (let (region
+        result
+        original-point)
+    (setq region (buffer-substring-no-properties (point-min) (point-max)))
+    (setq result (aide--openai-complete-string region))
+    (goto-char (point-max))
+    (setq original-point (point))
+    (if result
+        (progn
+          (insert "\n" result)
+          (fill-paragraph)
+          (let ((x (make-overlay original-point (point-max))))
+            (overlay-put x 'face '(:foreground "orange red")))
+          result)
+      (message "Empty result"))))
+
+(defun aide-openai-tldr-region (start end)
+  "Send the region to OpenAI autocomplete engine and get the TLDR result.
+START and END are selected region boundaries."
+  (interactive "r")
+  (let* ((region (buffer-substring-no-properties start end))
+         (result (aide--openai-complete-string (concat region "\n\n tl;dr:"))))
+    (message "%s" result)))
+
+(defun aide-openai-edits (api-key instruction input)
+  "Return the edits answer from OpenAI API.
+API-KEY is the OpenAI API key.
+INSTRUCTION and INPUT are the two params we send to the API."
+  (let ((result nil)
+        (auth-value (format "Bearer %s" api-key)))
+    (request
+      "https://api.openai.com/v1/engines/text-davinci-edit-001/edits"
+      :type "POST"
+      :data (json-encode `(("input" . ,input)
+                           ("instruction" . ,instruction)
+                           ("temperature" . 0.9)))
+      :headers `(("Authorization" . ,auth-value)
+                 ("Content-Type" . "application/json"))
+      :sync t
+      :parser 'json-read
+      :success (cl-function
+                (lambda (&key data &allow-other-keys)
+                  (setq result (alist-get 'text (elt (alist-get 'choices data) 0))))))
+    result))
+
+(defun aide-openai-edits-region-insert (start end)
+  "Send the region to OpenAI edits and insert the result to the end of region.
+START and END are selected region boundaries."
+  (interactive "r")
+  (let* ((region (buffer-substring-no-properties start end))
+         (result (aide-openai-edits openai-api-key "Rephrase the text" region)))
+    (goto-char end)
+    (if result
+        (progn
+          (insert "\n" result)
+          (fill-paragraph)
+          (let ((x (make-overlay end (point))))
+            (overlay-put x 'face '(:foreground "orange red")))
+          result)
+      (message "Empty result"))))
+
+(defun aide-openai-edits-region-replace (start end)
+  "Send the region to OpenAI edits and replace the region.
+START and END are selected region boundaries.
+The original content will be stored in the kill ring."
+  (interactive "r")
+  (let* ((region (buffer-substring-no-properties start end))
+         (result (aide-openai-edits openai-api-key "Rephrase the text" region)))
+    (goto-char end)
+    (if result
+        (progn
+          (kill-region start end)
+          (insert "\n" result)
+          (fill-paragraph)
+          (let ((x (make-overlay end (point))))
+            (overlay-put x 'face '(:foreground "orange red")))
+          result)
+      (message "Empty result"))))
+
+;; private
+
+(defun aide--openai-complete-string (string)
+  (aide-openai-complete openai-api-key string))
+
+(provide 'aide)
+;;; aide.el ends here
diff --git a/.emacs.d/lisp/dap-swi-prolog.el b/.emacs.d/lisp/dap-swi-prolog.el
new file mode 100644 (file)
index 0000000..058913a
--- /dev/null
@@ -0,0 +1,73 @@
+;;; dap-swi-prolog.el --- Debug Adapter Protocol mode for SWI-Prolog      -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Eshel Yaron
+
+;; Author: Eshel Yaron <eshelshay.yaron@gmail.com>
+;; Keywords: languages
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;; URL: https://github.com/yyoncho/dap-mode
+;; Package-Requires: ((emacs "25.1") (dash "2.14.1") (lsp-mode "4.0"))
+;; Version: 0.3
+
+;;; Commentary:
+;; Adapter for https://www.swi-prolog.org
+
+;;; Code:
+
+(require 'dap-mode)
+
+(defcustom dap-swi-prolog-debug-program
+    '("swipl" "-g" "[library(debug_adapter/main)]" "-t" "halt")
+  "The path to the SWI-Prolog debug adapter."
+  :group 'dap-swi-prolog
+  :type '(repeat string))
+
+(defun dap-swi-prolog--populate-start-file-args (conf)
+  "Populate CONF with the required arguments."
+  (let ((conf (-> conf
+                  (dap--put-if-absent :dap-server-path dap-swi-prolog-debug-program)
+                  (dap--put-if-absent :type "swi-prolog")
+                  (dap--put-if-absent :cwd default-directory)
+                  (dap--put-if-absent :module (buffer-file-name))
+                  (dap--put-if-absent :goal (read-string "?- " nil nil "true"))
+                  (dap--put-if-absent :name "SWI-Prolog Debug"))))
+    conf))
+
+(dap-register-debug-provider "swi-prolog" #'dap-swi-prolog--populate-start-file-args)
+
+(dap-register-debug-template "SWI-Prolog Run Configuration"
+                             (list :type "swi-prolog"
+                                   :request "launch"
+                                   :name "SWI-Prolog::Run"))
+(dap-register-debug-template "SWI-Prolog Start Terminal"
+                             (list :type "swi-prolog"
+                                   :goal "$run_in_terminal"
+                                   :request "launch"
+                                   :name "SWI-Prolog::Terminal"))
+
+(defun dap-swi-prolog--populate-start-tcp-args (conf)
+  "Populate CONF with the required arguments."
+  (let ((conf (-> conf
+                  (dap--put-if-absent :host "localhost")
+                  (dap--put-if-absent :debugServer 3443)
+                  (dap--put-if-absent :request "attach")
+                  (dap--put-if-absent :name "SWI-Prolog Debug"))))
+    conf))
+
+(dap-register-debug-provider "swi-prolog-tcp" #'dap-swi-prolog--populate-start-tcp-args)
+
+(provide 'dap-swi-prolog)
+;;; dap-swi-prolog.el ends here
diff --git a/.emacs.d/lisp/init-benchmarking.el b/.emacs.d/lisp/init-benchmarking.el
new file mode 100644 (file)
index 0000000..7c097c7
--- /dev/null
@@ -0,0 +1,75 @@
+;;; init-benchmarking.el --- Measure startup and require times -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+(defun sanityinc/time-subtract-millis (b a)
+  (* 1000.0 (float-time (time-subtract b a))))
+
+
+(defvar sanityinc/require-times nil
+  "A list of (FEATURE LOAD-START-TIME LOAD-DURATION).
+LOAD-DURATION is the time taken in milliseconds to load FEATURE.")
+
+(defun sanityinc/require-times-wrapper (orig feature &rest args)
+  "Note in `sanityinc/require-times' the time taken to require each feature."
+  (let* ((already-loaded (memq feature features))
+         (require-start-time (and (not already-loaded) (current-time))))
+    (prog1
+        (apply orig feature args)
+      (when (and (not already-loaded) (memq feature features))
+        (let ((time (sanityinc/time-subtract-millis (current-time) require-start-time)))
+          (add-to-list 'sanityinc/require-times
+                       (list feature require-start-time time)
+                       t))))))
+
+(advice-add 'require :around 'sanityinc/require-times-wrapper)
+
+
+(define-derived-mode sanityinc/require-times-mode tabulated-list-mode "Require-Times"
+  "Show times taken to `require' packages."
+  (setq tabulated-list-format
+        [("Start time (ms)" 20 sanityinc/require-times-sort-by-start-time-pred)
+         ("Feature" 30 t)
+         ("Time (ms)" 12 sanityinc/require-times-sort-by-load-time-pred)])
+  (setq tabulated-list-sort-key (cons "Start time (ms)" nil))
+  ;; (setq tabulated-list-padding 2)
+  (setq tabulated-list-entries #'sanityinc/require-times-tabulated-list-entries)
+  (tabulated-list-init-header)
+  (when (fboundp 'tablist-minor-mode)
+    (tablist-minor-mode)))
+
+(defun sanityinc/require-times-sort-by-start-time-pred (entry1 entry2)
+  (< (string-to-number (elt (nth 1 entry1) 0))
+     (string-to-number (elt (nth 1 entry2) 0))))
+
+(defun sanityinc/require-times-sort-by-load-time-pred (entry1 entry2)
+  (> (string-to-number (elt (nth 1 entry1) 2))
+     (string-to-number (elt (nth 1 entry2) 2))))
+
+(defun sanityinc/require-times-tabulated-list-entries ()
+  (cl-loop for (feature start-time millis) in sanityinc/require-times
+           with order = 0
+           do (incf order)
+           collect (list order
+                         (vector
+                          (format "%.3f" (sanityinc/time-subtract-millis start-time before-init-time))
+                          (symbol-name feature)
+                          (format "%.3f" millis)))))
+
+(defun sanityinc/require-times ()
+  "Show a tabular view of how long various libraries took to load."
+  (interactive)
+  (with-current-buffer (get-buffer-create "*Require Times*")
+    (sanityinc/require-times-mode)
+    (tabulated-list-revert)
+    (display-buffer (current-buffer))))
+
+
+(defun sanityinc/show-init-time ()
+  (message "init completed in %.2fms"
+           (sanityinc/time-subtract-millis after-init-time before-init-time)))
+
+(add-hook 'after-init-hook 'sanityinc/show-init-time)
+
+(provide 'init-benchmarking)
+;;; init-benchmarking.el ends here
diff --git a/.emacs.d/lisp/init-company.el b/.emacs.d/lisp/init-company.el
new file mode 100644 (file)
index 0000000..27cab4f
--- /dev/null
@@ -0,0 +1,30 @@
+;;; init-company.el --- Completion with company -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+;; WAITING: haskell-mode sets tags-table-list globally, breaks tags-completion-at-point-function
+;; TODO Default sort order should place [a-z] before punctuation
+
+(setq tab-always-indent 'complete)
+(add-to-list 'completion-styles 'initials t)
+
+(when (maybe-require-package 'company)
+  (add-hook 'after-init-hook 'global-company-mode)
+  (with-eval-after-load 'company
+    (diminish 'company-mode)
+;    (define-key company-mode-map (kbd "M-/") 'company-complete)
+    (define-key company-mode-map [remap completion-at-point] 'company-complete)
+    (define-key company-mode-map [remap indent-for-tab-command] 'company-indent-or-complete-common)
+;    (define-key company-active-map (kbd "M-/") 'company-other-backend)
+    (define-key company-active-map (kbd "C-n") 'company-select-next)
+    (define-key company-active-map (kbd "C-p") 'company-select-previous)
+    (define-key company-active-map (kbd "C-d") 'company-show-doc-buffer)
+    (define-key company-active-map (kbd "M-.") 'company-show-location)
+    (setq-default company-dabbrev-other-buffers 'all
+                  company-tooltip-align-annotations t))
+  (global-set-key (kbd "M-C-/") 'company-complete)
+  (when (maybe-require-package 'company-quickhelp)
+    (add-hook 'after-init-hook 'company-quickhelp-mode)))
+
+(provide 'init-company)
+;;; init-company.el ends here
diff --git a/.emacs.d/lisp/init-compile.el b/.emacs.d/lisp/init-compile.el
new file mode 100644 (file)
index 0000000..ac196b7
--- /dev/null
@@ -0,0 +1,67 @@
+;;; init-compile.el --- Helpers for M-x compile -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+(setq-default compilation-scroll-output t)
+
+(require-package 'alert)
+
+;; Customize `alert-default-style' to get messages after compilation
+
+(defun sanityinc/alert-after-compilation-finish (buf result)
+  "Use `alert' to report compilation RESULT if BUF is hidden."
+  (when (buffer-live-p buf)
+    (unless (catch 'is-visible
+              (walk-windows (lambda (w)
+                              (when (eq (window-buffer w) buf)
+                                (throw 'is-visible t))))
+              nil)
+      (alert (concat "Compilation " result)
+             :buffer buf
+             :category 'compilation))))
+
+(with-eval-after-load 'compile
+  (add-hook 'compilation-finish-functions
+            'sanityinc/alert-after-compilation-finish))
+
+(defvar sanityinc/last-compilation-buffer nil
+  "The last buffer in which compilation took place.")
+
+(with-eval-after-load 'compile
+  (defun sanityinc/save-compilation-buffer (&rest _)
+    "Save the compilation buffer to find it later."
+    (setq sanityinc/last-compilation-buffer next-error-last-buffer))
+  (advice-add 'compilation-start :after 'sanityinc/save-compilation-buffer)
+
+  (defun sanityinc/find-prev-compilation (orig &optional edit-command)
+    "Find the previous compilation buffer, if present, and recompile there."
+    (if (and (null edit-command)
+             (not (derived-mode-p 'compilation-mode))
+             sanityinc/last-compilation-buffer
+             (buffer-live-p (get-buffer sanityinc/last-compilation-buffer)))
+        (with-current-buffer sanityinc/last-compilation-buffer
+          (funcall orig edit-command))
+      (funcall orig edit-command)))
+  (advice-add 'recompile :around 'sanityinc/find-prev-compilation))
+
+(global-set-key [f6] 'recompile)
+
+
+(defun sanityinc/shell-command-in-view-mode (start end command &optional output-buffer replace &rest other-args)
+  "Put \"*Shell Command Output*\" buffers into view-mode."
+  (unless (or output-buffer replace)
+    (with-current-buffer "*Shell Command Output*"
+      (view-mode 1))))
+(advice-add 'shell-command-on-region :after 'sanityinc/shell-command-in-view-mode)
+
+
+(with-eval-after-load 'compile
+  (require 'ansi-color)
+  (defun sanityinc/colourise-compilation-buffer ()
+    (when (eq major-mode 'compilation-mode)
+      (ansi-color-apply-on-region compilation-filter-start (point-max))))
+  (add-hook 'compilation-filter-hook 'sanityinc/colourise-compilation-buffer))
+
+
+(provide 'init-compile)
+;;; init-compile.el ends here
diff --git a/.emacs.d/lisp/init-editing-utils.el b/.emacs.d/lisp/init-editing-utils.el
new file mode 100644 (file)
index 0000000..e803c6b
--- /dev/null
@@ -0,0 +1,308 @@
+;;; init-editing-utils.el --- Day-to-day editing helpers -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+(require-package 'unfill)
+
+;(when (fboundp 'electric-pair-mode) (add-hook 'after-init-hook 'electric-pair-mode))
+(add-hook 'after-init-hook 'electric-indent-mode)
+
+(maybe-require-package 'list-unicode-display)
+
+\f
+;;; Some basic preferences
+
+(setq-default
+ blink-cursor-interval 0.4
+ bookmark-default-file (locate-user-emacs-file ".bookmarks.el")
+ buffers-menu-max-size 30
+ case-fold-search t
+ column-number-mode t
+ ediff-split-window-function 'split-window-horizontally
+ ediff-window-setup-function 'ediff-setup-windows-plain
+ indent-tabs-mode nil
+ create-lockfiles nil
+ auto-save-default nil
+ make-backup-files nil
+ mouse-yank-at-point t
+ save-interprogram-paste-before-kill t
+ scroll-preserve-screen-position 'always
+ set-mark-command-repeat-pop t
+ tooltip-delay 1.5
+ truncate-lines nil
+ truncate-partial-width-windows nil)
+
+(add-hook 'after-init-hook 'delete-selection-mode)
+
+(add-hook 'after-init-hook 'global-auto-revert-mode)
+(setq global-auto-revert-non-file-buffers t
+      auto-revert-verbose nil)
+(with-eval-after-load 'autorevert
+  (diminish 'auto-revert-mode))
+
+(add-hook 'after-init-hook 'transient-mark-mode)
+
+
+\f
+;; Huge files
+
+(when (fboundp 'so-long-enable)
+  (add-hook 'after-init-hook 'so-long-enable))
+
+(require-package 'vlf)
+
+(defun ffap-vlf ()
+  "Find file at point with VLF."
+  (interactive)
+  (let ((file (ffap-file-at-point)))
+    (unless (file-exists-p file)
+      (error "File does not exist: %s" file))
+    (vlf file)))
+
+\f
+;;; A simple visible bell which works in all terminal types
+(require-package 'mode-line-bell)
+(add-hook 'after-init-hook 'mode-line-bell-mode)
+
+\f
+
+(when (maybe-require-package 'beacon)
+  (setq-default beacon-lighter "")
+  (setq-default beacon-size 20)
+  (add-hook 'after-init-hook 'beacon-mode))
+
+
+\f
+;;; Newline behaviour
+
+(global-set-key (kbd "RET") 'newline-and-indent)
+(defun sanityinc/newline-at-end-of-line ()
+  "Move to end of line, enter a newline, and reindent."
+  (interactive)
+  (move-end-of-line 1)
+  (newline-and-indent))
+
+(global-set-key (kbd "S-<return>") 'sanityinc/newline-at-end-of-line)
+
+\f
+
+(with-eval-after-load 'subword
+  (diminish 'subword-mode))
+
+\f
+
+(when (fboundp 'display-line-numbers-mode)
+  (setq-default display-line-numbers-width 3)
+  (add-hook 'prog-mode-hook 'display-line-numbers-mode))
+
+\f
+
+(when (boundp 'display-fill-column-indicator)
+  (setq-default indicate-buffer-boundaries 'left)
+  (setq-default display-fill-column-indicator-character ?\u254e)
+  (add-hook 'prog-mode-hook 'display-fill-column-indicator-mode))
+
+\f
+
+(when (require-package 'rainbow-delimiters)
+  (add-hook 'prog-mode-hook 'rainbow-delimiters-mode))
+
+\f
+
+(when (require-package 'expand-region)
+  (global-set-key (kbd "C-=") 'er/expand-region))
+
+\f
+(when (maybe-require-package 'symbol-overlay)
+  (dolist (hook '(prog-mode-hook html-mode-hook yaml-mode-hook conf-mode-hook))
+    (add-hook hook 'symbol-overlay-mode))
+  (with-eval-after-load 'symbol-overlay
+    (diminish 'symbol-overlay-mode)
+    (define-key symbol-overlay-mode-map (kbd "M-i") 'symbol-overlay-put)
+    (define-key symbol-overlay-mode-map (kbd "M-I") 'symbol-overlay-remove-all)
+    (define-key symbol-overlay-mode-map (kbd "M-n") 'symbol-overlay-jump-next)
+    (define-key symbol-overlay-mode-map (kbd "M-p") 'symbol-overlay-jump-prev)))
+
+\f
+;;; Zap *up* to char is a handy pair for zap-to-char
+(global-set-key (kbd "M-Z") 'zap-up-to-char)
+
+
+\f
+(require-package 'browse-kill-ring)
+(setq browse-kill-ring-separator "\f")
+(global-set-key (kbd "M-Y") 'browse-kill-ring)
+(with-eval-after-load 'browse-kill-ring
+  (define-key browse-kill-ring-mode-map (kbd "C-g") 'browse-kill-ring-quit)
+  (define-key browse-kill-ring-mode-map (kbd "M-n") 'browse-kill-ring-forward)
+  (define-key browse-kill-ring-mode-map (kbd "M-p") 'browse-kill-ring-previous))
+(with-eval-after-load 'page-break-lines
+  (add-to-list 'page-break-lines-modes 'browse-kill-ring-mode))
+
+
+;; Don't disable narrowing commands
+(put 'narrow-to-region 'disabled nil)
+(put 'narrow-to-page 'disabled nil)
+(put 'narrow-to-defun 'disabled nil)
+;; Don't disable case-change functions
+(put 'upcase-region 'disabled nil)
+(put 'downcase-region 'disabled nil)
+
+
+;; Show matching parens
+(add-hook 'after-init-hook 'show-paren-mode)
+
+
+\f
+;;; Handy key bindings
+
+(global-set-key (kbd "C-.") 'set-mark-command)
+(global-set-key (kbd "C-x C-.") 'pop-global-mark)
+
+(when (maybe-require-package 'avy)
+  (global-set-key (kbd "C-:") 'avy-goto-char-timer)
+  (global-set-key (kbd "C-'") 'avy-goto-char-2))
+
+(maybe-require-package 'iedit)
+
+(require-package 'multiple-cursors)
+;; multiple-cursors
+(global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
+(global-set-key (kbd "C->") 'mc/mark-next-like-this)
+(global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this)
+
+;; Train myself to use M-f and M-b instead
+(global-unset-key [M-left])
+(global-unset-key [M-right])
+
+(defun kill-back-to-indentation ()
+  "Kill from point back to the first non-whitespace character on the line."
+  (interactive)
+  (let ((prev-pos (point)))
+    (back-to-indentation)
+    (kill-region (point) prev-pos)))
+
+(global-set-key (kbd "C-M-<backspace>") 'kill-back-to-indentation)
+
+
+\f
+;;; Page break lines
+
+(when (maybe-require-package 'page-break-lines)
+  (add-hook 'after-init-hook 'global-page-break-lines-mode)
+  (with-eval-after-load 'page-break-lines
+    (diminish 'page-break-lines-mode)))
+
+
+\f
+;; Shift lines up and down with M-up and M-down. When paredit is enabled,
+;; it will use those keybindings. For this reason, you might prefer to
+;; use M-S-up and M-S-down, which will work even in lisp modes.
+
+(require-package 'move-dup)
+(global-set-key [M-up] 'move-dup-move-lines-up)
+(global-set-key [M-down] 'move-dup-move-lines-down)
+(global-set-key [M-S-up] 'move-dup-move-lines-up)
+(global-set-key [M-S-down] 'move-dup-move-lines-down)
+
+(global-set-key (kbd "C-c d") 'move-dup-duplicate-down)
+(global-set-key (kbd "C-c u") 'move-dup-duplicate-up)
+
+\f
+;;; Fix backward-up-list to understand quotes, see http://bit.ly/h7mdIL
+
+(defun sanityinc/backward-up-sexp (arg)
+  "Jump up to the start of the ARG'th enclosing sexp."
+  (interactive "p")
+  (let ((ppss (syntax-ppss)))
+    (cond ((elt ppss 3)
+           (goto-char (elt ppss 8))
+           (sanityinc/backward-up-sexp (1- arg)))
+          ((backward-up-list arg)))))
+
+(global-set-key [remap backward-up-list] 'sanityinc/backward-up-sexp) ; C-M-u, C-M-up
+
+
+\f
+;;; Cut/copy the current line if no region is active
+(require-package 'whole-line-or-region)
+(add-hook 'after-init-hook 'whole-line-or-region-global-mode)
+(with-eval-after-load 'whole-line-or-region
+  (diminish 'whole-line-or-region-local-mode))
+
+\f
+
+(defun sanityinc/open-line-with-reindent (n)
+  "A version of `open-line' which reindents the start and end positions.
+If there is a fill prefix and/or a `left-margin', insert them
+on the new line if the line would have been blank.
+With arg N, insert N newlines."
+  (interactive "*p")
+  (let* ((do-fill-prefix (and fill-prefix (bolp)))
+         (do-left-margin (and (bolp) (> (current-left-margin) 0)))
+         (loc (point-marker))
+         ;; Don't expand an abbrev before point.
+         (abbrev-mode nil))
+    (delete-horizontal-space t)
+    (newline n)
+    (indent-according-to-mode)
+    (when (eolp)
+      (delete-horizontal-space t))
+    (goto-char loc)
+    (while (> n 0)
+      (cond ((bolp)
+             (if do-left-margin (indent-to (current-left-margin)))
+             (if do-fill-prefix (insert-and-inherit fill-prefix))))
+      (forward-line 1)
+      (setq n (1- n)))
+    (goto-char loc)
+    (end-of-line)
+    (indent-according-to-mode)))
+
+(global-set-key (kbd "C-o") 'sanityinc/open-line-with-reindent)
+
+
+\f
+;; M-^ is inconvenient, so also bind M-j
+(global-set-key (kbd "M-j") 'join-line)
+
+\f
+;; Random line sorting
+(defun sanityinc/sort-lines-random (beg end)
+  "Sort lines in region from BEG to END randomly."
+  (interactive "r")
+  (save-excursion
+    (save-restriction
+      (narrow-to-region beg end)
+      (goto-char (point-min))
+      (let ;; To make `end-of-line' and etc. to ignore fields.
+          ((inhibit-field-text-motion t))
+        (sort-subr nil 'forward-line 'end-of-line nil nil
+                   (lambda (s1 s2) (eq (random 2) 0)))))))
+
+\f
+
+(require-package 'highlight-escape-sequences)
+(add-hook 'after-init-hook 'hes-mode)
+
+\f
+(require-package 'which-key)
+(add-hook 'after-init-hook 'which-key-mode)
+(setq-default which-key-idle-delay 1.5)
+(with-eval-after-load 'which-key
+  (diminish 'which-key-mode))
+
+\f
+(defun sanityinc/disable-features-during-macro-call (orig &rest args)
+  "When running a macro, disable features that might be expensive.
+ORIG is the advised function, which is called with its ARGS."
+  (let (post-command-hook
+        font-lock-mode
+        (tab-always-indent (or (eq 'complete tab-always-indent) tab-always-indent)))
+    (apply orig args)))
+
+(advice-add 'kmacro-call-macro :around 'sanityinc/disable-features-during-macro-call)
+
+
+(provide 'init-editing-utils)
+;;; init-editing-utils.el ends here
diff --git a/.emacs.d/lisp/init-elpa.el b/.emacs.d/lisp/init-elpa.el
new file mode 100644 (file)
index 0000000..358c5ee
--- /dev/null
@@ -0,0 +1,100 @@
+;;; init-elpa.el --- Settings and helpers for package.el -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+(require 'package)
+(require 'cl-lib)
+
+
+\f
+;;; On-demand installation of packages
+
+(defun require-package (package &optional min-version no-refresh)
+  "Install given PACKAGE, optionally requiring MIN-VERSION.
+If NO-REFRESH is non-nil, the available package lists will not be
+re-downloaded in order to locate PACKAGE."
+  (or (package-installed-p package min-version)
+      (let* ((known (cdr (assoc package package-archive-contents)))
+             (best (car (sort known (lambda (a b)
+                                      (version-list-<= (package-desc-version b)
+                                                       (package-desc-version a)))))))
+        (if (and best (version-list-<= min-version (package-desc-version best)))
+            (package-install best)
+          (if no-refresh
+              (error "No version of %s >= %S is available" package min-version)
+            (package-refresh-contents)
+            (require-package package min-version t)))
+        (package-installed-p package min-version))))
+
+(defun maybe-require-package (package &optional min-version no-refresh)
+  "Try to install PACKAGE, and return non-nil if successful.
+In the event of failure, return nil and print a warning message.
+Optionally require MIN-VERSION.  If NO-REFRESH is non-nil, the
+available package lists will not be re-downloaded in order to
+locate PACKAGE."
+  (condition-case err
+      (require-package package min-version no-refresh)
+    (error
+     (message "Couldn't install optional package `%s': %S" package err)
+     nil)))
+
+\f
+;;; Fire up package.el
+
+(setq package-enable-at-startup nil)
+(package-initialize)
+
+\f
+;; package.el updates the saved version of package-selected-packages correctly only
+;; after custom-file has been loaded, which is a bug. We work around this by adding
+;; the required packages to package-selected-packages after startup is complete.
+
+(defvar sanityinc/required-packages nil)
+
+(defun sanityinc/note-selected-package (oldfun package &rest args)
+  "If OLDFUN reports PACKAGE was successfully installed, note that fact.
+The package name is noted by adding it to
+`sanityinc/required-packages'.  This function is used as an
+advice for `require-package', to which ARGS are passed."
+  (let ((available (apply oldfun package args)))
+    (prog1
+        available
+      (when available
+        (add-to-list 'sanityinc/required-packages package)))))
+
+(advice-add 'require-package :around 'sanityinc/note-selected-package)
+
+(when (fboundp 'package--save-selected-packages)
+  (require-package 'seq)
+  (add-hook 'after-init-hook
+            (lambda ()
+              (package--save-selected-packages
+               (seq-uniq (append sanityinc/required-packages package-selected-packages))))))
+
+\f
+(require-package 'fullframe)
+(fullframe list-packages quit-window)
+
+\f
+(let ((package-check-signature nil))
+  (require-package 'gnu-elpa-keyring-update))
+
+\f
+(defun sanityinc/set-tabulated-list-column-width (col-name width)
+  "Set any column with name COL-NAME to the given WIDTH."
+  (when (> width (length col-name))
+    (cl-loop for column across tabulated-list-format
+             when (string= col-name (car column))
+             do (setf (elt column 1) width))))
+
+(defun sanityinc/maybe-widen-package-menu-columns ()
+  "Widen some columns of the package menu table to avoid truncation."
+  (when (boundp 'tabulated-list-format)
+    (sanityinc/set-tabulated-list-column-width "Version" 13)
+    (let ((longest-archive-name (apply 'max (mapcar 'length (mapcar 'car package-archives)))))
+      (sanityinc/set-tabulated-list-column-width "Archive" longest-archive-name))))
+
+(add-hook 'package-menu-mode-hook 'sanityinc/maybe-widen-package-menu-columns)
+
+(provide 'init-elpa)
+;;; init-elpa.el ends here
diff --git a/.emacs.d/lisp/init-exec-path.el b/.emacs.d/lisp/init-exec-path.el
new file mode 100644 (file)
index 0000000..557bfa9
--- /dev/null
@@ -0,0 +1,18 @@
+;;; init-exec-path.el --- Set up exec-path to help Emacs find programs  -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+(require-package 'exec-path-from-shell)
+
+(with-eval-after-load 'exec-path-from-shell
+  (dolist (var '("SSH_AUTH_SOCK" "SSH_AGENT_PID" "GPG_AGENT_INFO" "LANG" "LC_CTYPE" "NIX_SSL_CERT_FILE" "NIX_PATH"))
+    (add-to-list 'exec-path-from-shell-variables var)))
+
+
+(when (or (memq window-system '(mac ns x))
+          (unless (memq system-type '(ms-dos windows-nt))
+            (daemonp)))
+  (exec-path-from-shell-initialize))
+
+(provide 'init-exec-path)
+;;; init-exec-path.el ends here
diff --git a/.emacs.d/lisp/init-git.el b/.emacs.d/lisp/init-git.el
new file mode 100644 (file)
index 0000000..684d6b4
--- /dev/null
@@ -0,0 +1,102 @@
+;;; init-git.el --- Git SCM support -*- lexical-binding: t -*-
+;;; Commentary:
+
+;; See also init-github.el.
+
+;;; Code:
+
+;; TODO: link commits from vc-log to magit-show-commit
+;; TODO: smerge-mode
+(require-package 'git-blamed)
+(require-package 'gitignore-mode)
+(require-package 'gitconfig-mode)
+(when (maybe-require-package 'git-timemachine)
+  (global-set-key (kbd "C-x v t") 'git-timemachine-toggle))
+
+
+
+(when (maybe-require-package 'magit)
+  (setq-default magit-diff-refine-hunk t)
+
+  ;; Hint: customize `magit-repository-directories' so that you can use C-u M-F12 to
+  ;; quickly open magit on any one of your projects.
+  (global-set-key [(meta f12)] 'magit-status)
+  (global-set-key (kbd "C-x g") 'magit-status)
+  (global-set-key (kbd "C-x M-g") 'magit-dispatch)
+
+  (defun sanityinc/magit-or-vc-log-file (&optional prompt)
+    (interactive "P")
+    (if (and (buffer-file-name)
+             (eq 'Git (vc-backend (buffer-file-name))))
+        (if prompt
+            (magit-log-buffer-file-popup)
+          (magit-log-buffer-file t))
+      (vc-print-log)))
+
+  (with-eval-after-load 'vc
+    (define-key vc-prefix-map (kbd "l") 'sanityinc/magit-or-vc-log-file)))
+
+
+(with-eval-after-load 'magit
+  (define-key magit-status-mode-map (kbd "C-M-<up>") 'magit-section-up))
+
+
+(maybe-require-package 'magit-todos)
+
+(require-package 'fullframe)
+(with-eval-after-load 'magit
+  (fullframe magit-status magit-mode-quit-window))
+
+(when (maybe-require-package 'git-commit)
+  (add-hook 'git-commit-mode-hook 'goto-address-mode))
+
+\f
+(when *is-a-mac*
+  (with-eval-after-load 'magit
+    (add-hook 'magit-mode-hook (lambda () (local-unset-key [(meta h)])))))
+
+
+\f
+;; Convenient binding for vc-git-grep
+(with-eval-after-load 'vc
+  (define-key vc-prefix-map (kbd "f") 'vc-git-grep))
+
+
+\f
+;;; git-svn support
+
+;; (when (maybe-require-package 'magit-svn)
+;;   (require-package 'magit-svn)
+;;   (autoload 'magit-svn-enabled "magit-svn")
+;;   (defun sanityinc/maybe-enable-magit-svn-mode ()
+;;     (when (magit-svn-enabled)
+;;       (magit-svn-mode)))
+;;   (add-hook 'magit-status-mode-hook #'sanityinc/maybe-enable-magit-svn-mode))
+
+(with-eval-after-load 'compile
+  (dolist (defn (list '(git-svn-updated "^\t[A-Z]\t\\(.*\\)$" 1 nil nil 0 1)
+                      '(git-svn-needs-update "^\\(.*\\): needs update$" 1 nil nil 2 1)))
+    (add-to-list 'compilation-error-regexp-alist-alist defn)
+    (add-to-list 'compilation-error-regexp-alist (car defn))))
+
+(defvar git-svn--available-commands nil "Cached list of git svn subcommands")
+(defun git-svn--available-commands ()
+  (or git-svn--available-commands
+      (setq git-svn--available-commands
+            (sanityinc/string-all-matches
+             "^  \\([a-z\\-]+\\) +"
+             (shell-command-to-string "git svn help") 1))))
+
+(autoload 'vc-git-root "vc-git")
+
+(defun git-svn (dir command)
+  "Run a git svn subcommand in DIR."
+  (interactive (list (read-directory-name "Directory: ")
+                     (completing-read "git-svn command: " (git-svn--available-commands) nil t nil nil (git-svn--available-commands))))
+  (let* ((default-directory (vc-git-root dir))
+         (compilation-buffer-name-function (lambda (major-mode-name) "*git-svn*")))
+    (compile (concat "git svn " command))))
+
+
+(provide 'init-git)
+;;; init-git.el ends here
diff --git a/.emacs.d/lisp/init-github.el b/.emacs.d/lisp/init-github.el
new file mode 100644 (file)
index 0000000..f5b8b47
--- /dev/null
@@ -0,0 +1,16 @@
+;;; init-github.el --- Github integration -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+(require 'init-git)
+
+(maybe-require-package 'yagist)
+(require-package 'bug-reference-github)
+(add-hook 'prog-mode-hook 'bug-reference-prog-mode)
+
+(maybe-require-package 'github-clone)
+(maybe-require-package 'forge)
+(maybe-require-package 'github-review)
+
+(provide 'init-github)
+;;; init-github.el ends here
diff --git a/.emacs.d/lisp/init-go.el b/.emacs.d/lisp/init-go.el
new file mode 100644 (file)
index 0000000..e4a431d
--- /dev/null
@@ -0,0 +1,13 @@
+;;; init-go.el --- Go mode settings -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+(require 'go-mode)
+
+(add-hook 'go-mode-hook (lambda () (local-set-key (kbd "M-.") #'godef-jump)))
+(add-hook 'before-save-hook #'gofmt-before-save)
+(add-hook 'go-mode-hook #'flycheck-golangci-lint-setup)
+(setq flycheck-golangci-lint-config "/Users/eshelyaron/checkouts/dockerfile-normalizer/.golangci.yml")
+
+(provide 'init-go)
+;;; init-go.el ends here
diff --git a/.emacs.d/lisp/init-grep.el b/.emacs.d/lisp/init-grep.el
new file mode 100644 (file)
index 0000000..db2e261
--- /dev/null
@@ -0,0 +1,28 @@
+;;; init-grep.el --- Settings for grep and grep-like tools -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+(setq-default grep-highlight-matches t
+              grep-scroll-output t)
+
+(when *is-a-mac*
+  (setq-default locate-command "mdfind"))
+
+(require-package 'wgrep)
+(with-eval-after-load 'grep
+  (dolist (key (list (kbd "C-c C-q") (kbd "w")))
+    (define-key grep-mode-map key 'wgrep-change-to-wgrep-mode)))
+
+(when (and (executable-find "ag")
+           (maybe-require-package 'ag))
+  (require-package 'wgrep-ag)
+  (setq-default ag-highlight-search t)
+  (global-set-key (kbd "C-M-?") 'ag-project))
+
+(when (and (executable-find "rg")
+           (maybe-require-package 'rg))
+  (global-set-key (kbd "C-M-?") 'rg-project))
+
+
+(provide 'init-grep)
+;;; init-grep.el ends here
diff --git a/.emacs.d/lisp/init-gui-frames.el b/.emacs.d/lisp/init-gui-frames.el
new file mode 100644 (file)
index 0000000..fba5c95
--- /dev/null
@@ -0,0 +1,93 @@
+;;; init-gui-frames.el --- Behaviour specific to non-TTY frames -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+\f
+;; Stop C-z from minimizing windows under OS X
+
+(defun sanityinc/maybe-suspend-frame ()
+  (interactive)
+  (unless (and *is-a-mac* window-system)
+    (suspend-frame)))
+
+(global-set-key (kbd "C-z") 'sanityinc/maybe-suspend-frame)
+
+
+\f
+;; Suppress GUI features
+
+(setq use-file-dialog nil)
+(setq use-dialog-box nil)
+(setq inhibit-startup-screen t)
+
+
+\f
+;; Window size and features
+
+(setq-default
+ window-resize-pixelwise t
+ frame-resize-pixelwise t)
+
+(when (fboundp 'tool-bar-mode)
+  (tool-bar-mode -1))
+(when (fboundp 'set-scroll-bar-mode)
+  (set-scroll-bar-mode nil))
+
+(menu-bar-mode -1)
+
+(let ((no-border '(internal-border-width . 0)))
+  (add-to-list 'default-frame-alist no-border)
+  (add-to-list 'initial-frame-alist no-border))
+
+(defun sanityinc/adjust-opacity (frame incr)
+  "Adjust the background opacity of FRAME by increment INCR."
+  (unless (display-graphic-p frame)
+    (error "Cannot adjust opacity of this frame"))
+  (let* ((oldalpha (or (frame-parameter frame 'alpha) 100))
+         ;; The 'alpha frame param became a pair at some point in
+         ;; emacs 24.x, e.g. (100 100)
+         (oldalpha (if (listp oldalpha) (car oldalpha) oldalpha))
+         (newalpha (+ incr oldalpha)))
+    (when (and (<= frame-alpha-lower-limit newalpha) (>= 100 newalpha))
+      (modify-frame-parameters frame (list (cons 'alpha newalpha))))))
+
+(when (and *is-a-mac* (fboundp 'toggle-frame-fullscreen))
+  ;; Command-Option-f to toggle fullscreen mode
+  ;; Hint: Customize `ns-use-native-fullscreen'
+  (global-set-key (kbd "C-s-f") 'toggle-frame-fullscreen))
+
+;; TODO: use seethru package instead?
+(global-set-key (kbd "M-C-8") (lambda () (interactive) (sanityinc/adjust-opacity nil -2)))
+(global-set-key (kbd "M-C-9") (lambda () (interactive) (sanityinc/adjust-opacity nil 2)))
+(global-set-key (kbd "M-C-7") (lambda () (interactive) (modify-frame-parameters nil `((alpha . 100)))))
+
+
+(when *is-a-mac*
+  (when (maybe-require-package 'ns-auto-titlebar)
+    (ns-auto-titlebar-mode)))
+
+
+(setq frame-title-format
+      '((:eval (if (buffer-file-name)
+                   (abbreviate-file-name (buffer-file-name))
+                 "%b"))))
+
+;; Non-zero values for `line-spacing' can mess up ansi-term and co,
+;; so we zero it explicitly in those cases.
+(add-hook 'term-mode-hook
+          (lambda ()
+            (setq line-spacing 0)))
+
+\f
+;; Change global font size easily
+
+(require-package 'default-text-scale)
+(add-hook 'after-init-hook 'default-text-scale-mode)
+
+
+\f
+(require-package 'disable-mouse)
+
+
+(provide 'init-gui-frames)
+;;; init-gui-frames.el ends here
diff --git a/.emacs.d/lisp/init-helpful.el b/.emacs.d/lisp/init-helpful.el
new file mode 100644 (file)
index 0000000..a10187c
--- /dev/null
@@ -0,0 +1,11 @@
+;;; init-helpful.el --- Help with helpful -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+(when (maybe-require-package 'helpful)
+  (global-set-key (kbd "C-h f") #'helpful-callable)
+  (global-set-key (kbd "C-h v") #'helpful-variable)
+  (global-set-key (kbd "C-h k") #'helpful-key))
+
+(provide 'init-helpful)
+;;; init-helpful.el ends here
diff --git a/.emacs.d/lisp/init-hippie-expand.el b/.emacs.d/lisp/init-hippie-expand.el
new file mode 100644 (file)
index 0000000..156819a
--- /dev/null
@@ -0,0 +1,15 @@
+;;; init-hippie-expand.el --- Settings for hippie-expand -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+(global-set-key (kbd "M-/") 'hippie-expand)
+
+(setq hippie-expand-try-functions-list
+      '(try-complete-file-name-partially
+        try-complete-file-name
+        try-expand-dabbrev
+        try-expand-dabbrev-all-buffers
+        try-expand-dabbrev-from-kill))
+
+(provide 'init-hippie-expand)
+;;; init-hippie-expand.el ends here
diff --git a/.emacs.d/lisp/init-ialign.el b/.emacs.d/lisp/init-ialign.el
new file mode 100644 (file)
index 0000000..933d3c0
--- /dev/null
@@ -0,0 +1,9 @@
+;;; init-ialign.el --- Alignment with ialign -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+(when (maybe-require-package 'ialign)
+  (global-set-key (kbd "C-x l") #'ialign))
+
+(provide 'init-ialign)
+;;; init-ialign.el ends here
diff --git a/.emacs.d/lisp/init-ibuffer.el b/.emacs.d/lisp/init-ibuffer.el
new file mode 100644 (file)
index 0000000..672dee8
--- /dev/null
@@ -0,0 +1,58 @@
+;;; init-ibuffer.el --- ibuffer settings -*- lexical-binding: t -*-
+;;; Commentary:
+
+;; TODO: enhance ibuffer-fontification-alist
+;;   See http://www.reddit.com/r/emacs/comments/21fjpn/fontifying_buffer_list_for_emacs_243/
+
+;;; Code:
+
+(require-package 'fullframe)
+(with-eval-after-load 'ibuffer
+ (fullframe ibuffer ibuffer-quit))
+
+(require-package 'ibuffer-vc)
+
+(defun ibuffer-set-up-preferred-filters ()
+  (ibuffer-vc-set-filter-groups-by-vc-root)
+  (unless (eq ibuffer-sorting-mode 'filename/process)
+    (ibuffer-do-sort-by-filename/process)))
+
+(add-hook 'ibuffer-hook 'ibuffer-set-up-preferred-filters)
+
+(setq-default ibuffer-show-empty-filter-groups nil)
+
+
+(with-eval-after-load 'ibuffer
+  ;; Use human readable Size column instead of original one
+  (define-ibuffer-column size-h
+    (:name "Size" :inline t)
+    (file-size-human-readable (buffer-size))))
+
+
+;; Modify the default ibuffer-formats (toggle with `)
+(setq ibuffer-formats
+      '((mark modified read-only vc-status-mini " "
+              (name 22 22 :left :elide)
+              " "
+              (size-h 9 -1 :right)
+              " "
+              (mode 12 12 :left :elide)
+              " "
+              vc-relative-file)
+        (mark modified read-only vc-status-mini " "
+              (name 22 22 :left :elide)
+              " "
+              (size-h 9 -1 :right)
+              " "
+              (mode 14 14 :left :elide)
+              " "
+              (vc-status 12 12 :left)
+              " "
+              vc-relative-file)))
+
+(setq ibuffer-filter-group-name-face 'font-lock-doc-face)
+
+(global-set-key (kbd "C-x C-b") 'ibuffer)
+
+(provide 'init-ibuffer)
+;;; init-ibuffer.el ends here
diff --git a/.emacs.d/lisp/init-idris2.el b/.emacs.d/lisp/init-idris2.el
new file mode 100644 (file)
index 0000000..3a648f0
--- /dev/null
@@ -0,0 +1,13 @@
+;;; init-idris2.el --- Idris2 mode settings -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+(add-to-list 'load-path "~/.emacs.d/idris2-mode/")
+
+(require 'idris2-mode)
+
+(add-to-list 'auto-mode-alist '("\\.idr\\'" . idris2-mode))
+
+
+(provide 'init-idris2)
+;;; init-idris2.el ends here
diff --git a/.emacs.d/lisp/init-isearch.el b/.emacs.d/lisp/init-isearch.el
new file mode 100644 (file)
index 0000000..b3316df
--- /dev/null
@@ -0,0 +1,50 @@
+;;; init-isearch.el --- isearch settings -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+;; Show number of matches while searching
+(when (maybe-require-package 'anzu)
+  (add-hook 'after-init-hook 'global-anzu-mode)
+  (setq anzu-mode-lighter "")
+  (global-set-key [remap query-replace-regexp] 'anzu-query-replace-regexp)
+  (global-set-key [remap query-replace] 'anzu-query-replace))
+
+(with-eval-after-load 'isearch
+  ;; DEL during isearch should edit the search string, not jump back to the previous result
+  (define-key isearch-mode-map [remap isearch-delete-char] 'isearch-del-char)
+
+  ;; Activate occur easily inside isearch
+  (when (fboundp 'isearch-occur)
+    ;; to match ivy conventions
+    (define-key isearch-mode-map (kbd "C-c C-o") 'isearch-occur)))
+
+;; Search back/forth for the symbol at point
+;; See http://www.emacswiki.org/emacs/SearchAtPoint
+(defun isearch-yank-symbol ()
+  "*Put symbol at current point into search string."
+  (interactive)
+  (let ((sym (thing-at-point 'symbol)))
+    (if sym
+        (progn
+          (setq isearch-regexp t
+                isearch-string (concat "\\_<" (regexp-quote sym) "\\_>")
+                isearch-message (mapconcat 'isearch-text-char-description isearch-string "")
+                isearch-yank-flag t))
+      (ding)))
+  (isearch-search-and-update))
+
+(define-key isearch-mode-map "\C-\M-w" 'isearch-yank-symbol)
+
+
+(defun sanityinc/isearch-exit-other-end ()
+  "Exit isearch, but at the other end of the search string.
+This is useful when followed by an immediate kill."
+  (interactive)
+  (isearch-exit)
+  (goto-char isearch-other-end))
+
+(define-key isearch-mode-map [(control return)] 'sanityinc/isearch-exit-other-end)
+
+
+(provide 'init-isearch)
+;;; init-isearch.el ends here
diff --git a/.emacs.d/lisp/init-keyfreq.el b/.emacs.d/lisp/init-keyfreq.el
new file mode 100644 (file)
index 0000000..a6b3f4b
--- /dev/null
@@ -0,0 +1,16 @@
+;;; init-keyfreq.el --- Command frequency logging with keyfreq -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+(when (maybe-require-package 'keyfreq)
+  (keyfreq-mode 1)
+  (keyfreq-autosave-mode 1)
+  (setq keyfreq-excluded-commands
+        '(self-insert-command
+          forward-char
+          backward-char
+          previous-line
+          next-line)))
+
+(provide 'init-keyfreq)
+;;; init-keyfreq.el ends here
diff --git a/.emacs.d/lisp/init-minibuffer.el b/.emacs.d/lisp/init-minibuffer.el
new file mode 100644 (file)
index 0000000..74c3fd6
--- /dev/null
@@ -0,0 +1,64 @@
+;;; init-minibuffer.el --- Config for minibuffer completion       -*- lexical-binding: t; -*-
+;;; Commentary:
+;;; Code:
+
+
+(when (maybe-require-package 'vertico)
+  (add-hook 'after-init-hook 'vertico-mode)
+
+  (require-package 'orderless)
+  (with-eval-after-load 'vertico
+    (require 'orderless))
+
+  (defun sanityinc/use-orderless-in-minibuffer ()
+    (setq-local completion-styles '(substring orderless)))
+  (add-hook 'minibuffer-setup-hook 'sanityinc/use-orderless-in-minibuffer)
+
+  (when (maybe-require-package 'embark)
+    (with-eval-after-load 'vertico
+      (define-key vertico-map (kbd "C-c C-o") 'embark-export)
+      (define-key vertico-map (kbd "C-c C-c") 'embark-act)))
+
+  (when (maybe-require-package 'consult)
+    (defmacro sanityinc/no-consult-preview (&rest cmds)
+      `(with-eval-after-load 'consult
+         (consult-customize ,@cmds :preview-key (kbd "M-P"))))
+
+    (sanityinc/no-consult-preview
+     consult-ripgrep
+     consult-git-grep consult-grep
+     consult-bookmark consult-recent-file consult-xref
+     consult--source-bookmark)
+
+    (when (maybe-require-package 'projectile)
+      (setq-default consult-project-root-function 'projectile-project-root))
+
+    (when (and (executable-find "rg") (maybe-require-package 'affe))
+      (defun sanityinc/affe-grep-at-point (&optional dir initial)
+        (interactive (list prefix-arg (when-let ((s (symbol-at-point)))
+                                        (symbol-name s))))
+        (affe-grep dir initial))
+      (global-set-key (kbd "C-M-?") 'sanityinc/affe-grep-at-point)
+      (sanityinc/no-consult-preview sanityinc/affe-grep-at-point)
+      (with-eval-after-load 'affe (sanityinc/no-consult-preview affe-grep)))
+
+    (global-set-key [remap switch-to-buffer] 'consult-buffer)
+    (global-set-key [remap switch-to-buffer-other-window] 'consult-buffer-other-window)
+    (global-set-key [remap switch-to-buffer-other-frame] 'consult-buffer-other-frame)
+    (global-set-key [remap goto-line] 'consult-goto-line)
+
+
+
+    (when (maybe-require-package 'embark-consult)
+      (with-eval-after-load 'embark
+        (require 'embark-consult)
+        (add-hook 'embark-collect-mode-hook 'embark-consult-preview-minor-mode)))
+
+    (maybe-require-package 'consult-flycheck)))
+
+(when (maybe-require-package 'marginalia)
+  (add-hook 'after-init-hook 'marginalia-mode))
+
+
+(provide 'init-minibuffer)
+;;; init-minibuffer.el ends here
diff --git a/.emacs.d/lisp/init-pdf.el b/.emacs.d/lisp/init-pdf.el
new file mode 100644 (file)
index 0000000..58d7bca
--- /dev/null
@@ -0,0 +1,10 @@
+;;; init-pdf.el --- PDF support -*- lexical-binding: t -*-
+;;; Commentary:
+
+;;; Code:
+
+(when (maybe-require-package 'pdf-tools)
+  (add-hook 'pdf-view-mode-hook 'pdf-tools-install))
+
+(provide 'init-pdf)
+;;; init-pdf.el ends here
diff --git a/.emacs.d/lisp/init-projectile.el b/.emacs.d/lisp/init-projectile.el
new file mode 100644 (file)
index 0000000..9d9f8f5
--- /dev/null
@@ -0,0 +1,22 @@
+;;; init-projectile.el --- Use Projectile for navigation within projects -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+(when (maybe-require-package 'projectile)
+  (add-hook 'after-init-hook 'projectile-mode)
+
+  ;; Shorter modeline
+  (setq-default projectile-mode-line-prefix " Proj")
+
+  (when (executable-find "rg")
+    (setq-default projectile-generic-command "rg --files --hidden"))
+
+  (with-eval-after-load 'projectile
+    (define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map))
+
+  (maybe-require-package 'ibuffer-projectile)
+  (maybe-require-package 'ggtags))
+
+
+(provide 'init-projectile)
+;;; init-projectile.el ends here
diff --git a/.emacs.d/lisp/init-prolog.el b/.emacs.d/lisp/init-prolog.el
new file mode 100644 (file)
index 0000000..6f45e66
--- /dev/null
@@ -0,0 +1,72 @@
+;;; init-prolog.el --- Command frequency logging with keyfreq -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+(add-to-list 'auto-mode-alist '("\\.pl\\'" . prolog-mode))
+(add-to-list 'auto-mode-alist '("\\.plt\\'" . prolog-mode))
+
+(maybe-require-package 'ediprolog)
+
+(when (maybe-require-package 'dap-mode)
+  (require 'dap-ui)
+  (require 'dap-swi-prolog)
+  (require 'vterm))
+
+(require 'showterm)
+
+(defun prolog-create-predicate-at-point ()
+  "foo"
+  (interactive)
+  (progn
+    (save-buffer)
+    (prolog-ensure-process)
+    (process-send-string "prolog" (concat "ie:create_predicate_at_point('" (buffer-file-name) "', " (number-to-string (point)) ").\n"))))
+
+(defun prolog-term-list-at-point ()
+  "bar"
+  (interactive)
+  (progn
+    (save-buffer)
+    (read (shell-command-to-string (concat "swipl -g \"ie:show_enclosing_ranges_at_point('" (buffer-file-name) "', " (number-to-string (point)) ")\" -t halt")))))
+
+(defun dap-swi-prolog-internal-terminal (command title debug-session)
+  "foo"
+  (term command))
+
+(global-set-key (kbd "C-c C-o") 'prolog-create-predicate-at-point)
+
+
+(defun dap-swi-prolog--populate-start-tcp-args (conf)
+  "Populate CONF with the required arguments."
+  (let ((conf (-> conf
+                  (dap--put-if-absent :host "localhost")
+                  (dap--put-if-absent :debugServer 3443)
+                  (dap--put-if-absent :request "attach")
+                  (dap--put-if-absent :name "SWI-Prolog Debug"))))
+    conf))
+
+(dap-register-debug-provider "swi-prolog-tcp" #'dap-swi-prolog--populate-start-tcp-args)
+
+;(require 'lsp)
+;
+;(lsp-register-client
+; (make-lsp-client :new-connection (lsp-stdio-connection (list "swipl"
+;                                                              "-g" "use_module(library(lsp_server))."
+;                                                              "-g" "lsp_server:main"
+;                                                              "-t" "halt"
+;                                                              "--" "stdio"))
+;                  :activation-fn (lsp-activate-on "prolog")
+;                  :priority -1
+;                  :server-id 'prolog-ls))
+;
+;(add-hook 'prolog-mode-hook #'lsp)
+
+
+(define-derived-mode dapscript-mode
+  prolog-mode "DAP script"
+  "Major mode for dapscript source files."
+  (flycheck-mode))
+
+(add-to-list 'auto-mode-alist '("\\.dapscript\\'" . dapscript-mode))
+(provide 'init-prolog)
+;;; init-prolog.el ends here
diff --git a/.emacs.d/lisp/init-recentf.el b/.emacs.d/lisp/init-recentf.el
new file mode 100644 (file)
index 0000000..983fc89
--- /dev/null
@@ -0,0 +1,12 @@
+;;; init-recentf.el --- Settings for tracking recent files -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+(add-hook 'after-init-hook 'recentf-mode)
+(setq-default
+ recentf-max-saved-items 1000
+ recentf-exclude `("/tmp/" "/ssh:" ,(concat package-user-dir "/.*-autoloads\\.el\\'")))
+
+
+(provide 'init-recentf)
+;;; init-recentf.el ends here
diff --git a/.emacs.d/lisp/init-site-lisp.el b/.emacs.d/lisp/init-site-lisp.el
new file mode 100644 (file)
index 0000000..8b190ab
--- /dev/null
@@ -0,0 +1,54 @@
+;;; init-site-lisp.el --- Support elisp manually installed in the site-lisp dir -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+;;; Set load path
+
+(require 'cl-lib)
+
+(defun sanityinc/add-subdirs-to-load-path (parent-dir)
+  "Add every non-hidden subdir of PARENT-DIR to `load-path'."
+  (let ((default-directory parent-dir))
+    (setq load-path
+          (append
+           (cl-remove-if-not
+            #'file-directory-p
+            (directory-files (expand-file-name parent-dir) t "^[^\\.]"))
+           load-path))))
+
+;; Add both site-lisp and its immediate subdirs to `load-path'
+(let ((site-lisp-dir (expand-file-name "site-lisp/" user-emacs-directory)))
+  (push site-lisp-dir load-path)
+  (sanityinc/add-subdirs-to-load-path site-lisp-dir))
+
+\f;;; Utilities for grabbing upstream libs
+
+(defun site-lisp-dir-for (name)
+  (expand-file-name (format "site-lisp/%s" name) user-emacs-directory))
+
+(defun site-lisp-library-el-path (name)
+  (expand-file-name (format "%s.el" name) (site-lisp-dir-for name)))
+
+(defun download-site-lisp-module (name url)
+  (let ((dir (site-lisp-dir-for name)))
+    (message "Downloading %s from %s" name url)
+    (unless (file-directory-p dir)
+      (make-directory dir t))
+    (add-to-list 'load-path dir)
+    (let ((el-file (site-lisp-library-el-path name)))
+      (url-copy-file url el-file t nil)
+      el-file)))
+
+(defun ensure-lib-from-url (name url)
+  (unless (site-lisp-library-loadable-p name)
+    (byte-compile-file (download-site-lisp-module name url))))
+
+(defun site-lisp-library-loadable-p (name)
+  "Return whether or not the library `name' can be loaded from a
+source file under ~/.emacs.d/site-lisp/name/"
+  (let ((f (locate-library (symbol-name name))))
+    (and f (string-prefix-p (file-name-as-directory (site-lisp-dir-for name)) f))))
+
+
+(provide 'init-site-lisp)
+;;; init-site-lisp.el ends here
diff --git a/.emacs.d/lisp/init-themes.el b/.emacs.d/lisp/init-themes.el
new file mode 100644 (file)
index 0000000..e97d412
--- /dev/null
@@ -0,0 +1,24 @@
+;;; init-themes.el --- Defaults for themes -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+;; Don't prompt to confirm theme safety. This avoids problems with
+;; first-time startup on Emacs > 26.3.
+(setq custom-safe-themes t)
+
+(when (maybe-require-package 'zenburn-theme)
+  ;; If you don't customize it, this is the theme you get.
+  (setq-default custom-enabled-themes '(zenburn)))
+
+;; Ensure that themes will be applied even if they have not been customized
+(defun reapply-themes ()
+  "Forcibly load the themes listed in `custom-enabled-themes'."
+  (dolist (theme custom-enabled-themes)
+    (unless (custom-theme-p theme)
+      (load-theme theme)))
+  (custom-set-variables `(custom-enabled-themes (quote ,custom-enabled-themes))))
+
+(add-hook 'after-init-hook 'reapply-themes)
+
+(provide 'init-themes)
+;;; init-themes.el ends here
diff --git a/.emacs.d/lisp/init-utils.el b/.emacs.d/lisp/init-utils.el
new file mode 100644 (file)
index 0000000..cff9fab
--- /dev/null
@@ -0,0 +1,81 @@
+;;; init-utils.el --- Elisp helper functions and commands -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+(define-obsolete-function-alias 'after-load 'with-eval-after-load "")
+
+\f
+;; Handier way to add modes to auto-mode-alist
+(defun add-auto-mode (mode &rest patterns)
+  "Add entries to `auto-mode-alist' to use `MODE' for all given file `PATTERNS'."
+  (dolist (pattern patterns)
+    (add-to-list 'auto-mode-alist (cons pattern mode))))
+
+;; Like diminish, but for major modes
+(defun sanityinc/set-major-mode-name (name)
+  "Override the major mode NAME in this buffer."
+  (setq-local mode-name name))
+
+(defun sanityinc/major-mode-lighter (mode name)
+  (add-hook (derived-mode-hook-name mode)
+            (apply-partially 'sanityinc/set-major-mode-name name)))
+
+\f
+;; String utilities missing from core emacs
+
+(defun sanityinc/string-all-matches (regex str &optional group)
+  "Find all matches for `REGEX' within `STR', returning the full match string or group `GROUP'."
+  (let ((result nil)
+        (pos 0)
+        (group (or group 0)))
+    (while (string-match regex str pos)
+      (push (match-string group str) result)
+      (setq pos (match-end group)))
+    result))
+
+
+\f
+;; Delete the current file
+
+(defun delete-this-file ()
+  "Delete the current file, and kill the buffer."
+  (interactive)
+  (unless (buffer-file-name)
+    (error "No file is currently being edited"))
+  (when (yes-or-no-p (format "Really delete '%s'?"
+                             (file-name-nondirectory buffer-file-name)))
+    (delete-file (buffer-file-name))
+    (kill-this-buffer)))
+
+
+\f
+;; Rename the current file
+
+(defun rename-this-file-and-buffer (new-name)
+  "Renames both current buffer and file it's visiting to NEW-NAME."
+  (interactive "sNew name: ")
+  (let ((name (buffer-name))
+        (filename (buffer-file-name)))
+    (unless filename
+      (error "Buffer '%s' is not visiting a file!" name))
+    (progn
+      (when (file-exists-p filename)
+        (rename-file filename new-name 1))
+      (set-visited-file-name new-name)
+      (rename-buffer new-name))))
+
+\f
+;; Browse current HTML file
+
+(defun browse-current-file ()
+  "Open the current file as a URL using `browse-url'."
+  (interactive)
+  (let ((file-name (buffer-file-name)))
+    (if (and (fboundp 'tramp-tramp-file-p)
+             (tramp-tramp-file-p file-name))
+        (error "Cannot open tramp file")
+      (browse-url (concat "file://" file-name)))))
+
+
+(provide 'init-utils)
+;;; init-utils.el ends here
diff --git a/.emacs.d/lisp/init-vc.el b/.emacs.d/lisp/init-vc.el
new file mode 100644 (file)
index 0000000..09b2084
--- /dev/null
@@ -0,0 +1,21 @@
+;;; init-vc.el --- Version control support -*- lexical-binding: t -*-
+;;; Commentary:
+
+;; Most version control packages are configured separately: see
+;; init-git.el, for example.
+
+;;; Code:
+
+(when (maybe-require-package 'diff-hl)
+  (add-hook 'magit-post-refresh-hook 'diff-hl-magit-post-refresh)
+  (add-hook 'after-init-hook 'global-diff-hl-mode)
+
+  (with-eval-after-load 'diff-hl
+    (define-key diff-hl-mode-map
+      (kbd "<left-fringe> <mouse-1>")
+      'diff-hl-diff-goto-hunk)))
+
+(maybe-require-package 'browse-at-remote)
+
+(provide 'init-vc)
+;;; init-vc.el ends here
diff --git a/.emacs.d/lisp/init-web.el b/.emacs.d/lisp/init-web.el
new file mode 100644 (file)
index 0000000..128507e
--- /dev/null
@@ -0,0 +1,10 @@
+;;; init-web.el --- Browse with w3m -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+(when (maybe-require-package 'w3m)
+  (setq browse-url-browser-function 'w3m-browse-url)
+  (autoload 'w3m-browse-url "w3m" "Ask a WWW browser to show a URL." t))
+
+(provide 'init-web)
+;;; init-web.el ends here
diff --git a/.emacs.d/lisp/init-web.pl b/.emacs.d/lisp/init-web.pl
new file mode 100644 (file)
index 0000000..a10187c
--- /dev/null
@@ -0,0 +1,11 @@
+;;; init-helpful.el --- Help with helpful -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+(when (maybe-require-package 'helpful)
+  (global-set-key (kbd "C-h f") #'helpful-callable)
+  (global-set-key (kbd "C-h v") #'helpful-variable)
+  (global-set-key (kbd "C-h k") #'helpful-key))
+
+(provide 'init-helpful)
+;;; init-helpful.el ends here
diff --git a/.emacs.d/lisp/init-whitespace.el b/.emacs.d/lisp/init-whitespace.el
new file mode 100644 (file)
index 0000000..b208215
--- /dev/null
@@ -0,0 +1,27 @@
+;;; init-whitespace.el --- Special handling for whitespace -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+(setq-default show-trailing-whitespace nil)
+
+\f
+;;; Whitespace
+
+(defun sanityinc/show-trailing-whitespace ()
+  "Enable display of trailing whitespace in this buffer."
+  (setq-local show-trailing-whitespace t))
+
+(dolist (hook '(prog-mode-hook text-mode-hook conf-mode-hook))
+  (add-hook hook 'sanityinc/show-trailing-whitespace))
+
+
+(require-package 'whitespace-cleanup-mode)
+(add-hook 'after-init-hook 'global-whitespace-cleanup-mode)
+(with-eval-after-load 'whitespace-cleanup-mode
+  (diminish 'whitespace-cleanup-mode))
+
+(global-set-key [remap just-one-space] 'cycle-spacing)
+
+
+(provide 'init-whitespace)
+;;; init-whitespace.el ends here
diff --git a/.emacs.d/lisp/init-windows.el b/.emacs.d/lisp/init-windows.el
new file mode 100644 (file)
index 0000000..1c99684
--- /dev/null
@@ -0,0 +1,113 @@
+;;; init-windows.el --- Working with windows within frames -*- lexical-binding: t -*-
+;;; Commentary:
+
+;; This is not about the "Windows" OS, but rather Emacs's "windows"
+;; concept: these are the panels within an Emacs frame which contain
+;; buffers.
+
+;;; Code:
+
+;; Navigate window layouts with "C-c <left>" and "C-c <right>"
+
+(add-hook 'after-init-hook 'winner-mode)
+
+\f
+;; Make "C-x o" prompt for a target window when there are more than 2
+(require-package 'switch-window)
+(setq-default switch-window-shortcut-style 'alphabet)
+(setq-default switch-window-timeout nil)
+(global-set-key (kbd "C-x o") 'switch-window)
+
+
+\f
+;; When splitting window, show (other-buffer) in the new window
+
+(defun split-window-func-with-other-buffer (split-function)
+  (lambda (&optional arg)
+    "Split this window and switch to the new window unless ARG is provided."
+    (interactive "P")
+    (funcall split-function)
+    (let ((target-window (next-window)))
+      (set-window-buffer target-window (other-buffer))
+      (unless arg
+        (select-window target-window)))))
+
+(global-set-key (kbd "C-x 2") (split-window-func-with-other-buffer 'split-window-vertically))
+(global-set-key (kbd "C-x 3") (split-window-func-with-other-buffer 'split-window-horizontally))
+
+(defun sanityinc/toggle-delete-other-windows ()
+  "Delete other windows in frame if any, or restore previous window config."
+  (interactive)
+  (if (and winner-mode
+           (equal (selected-window) (next-window)))
+      (winner-undo)
+    (delete-other-windows)))
+
+(global-set-key (kbd "C-x 1") 'sanityinc/toggle-delete-other-windows)
+
+\f
+;; Rearrange split windows
+
+(defun split-window-horizontally-instead ()
+  "Kill any other windows and re-split such that the current window is on the top half of the frame."
+  (interactive)
+  (let ((other-buffer (and (next-window) (window-buffer (next-window)))))
+    (delete-other-windows)
+    (split-window-horizontally)
+    (when other-buffer
+      (set-window-buffer (next-window) other-buffer))))
+
+(defun split-window-vertically-instead ()
+  "Kill any other windows and re-split such that the current window is on the left half of the frame."
+  (interactive)
+  (let ((other-buffer (and (next-window) (window-buffer (next-window)))))
+    (delete-other-windows)
+    (split-window-vertically)
+    (when other-buffer
+      (set-window-buffer (next-window) other-buffer))))
+
+(global-set-key (kbd "C-x |") 'split-window-horizontally-instead)
+(global-set-key (kbd "C-x _") 'split-window-vertically-instead)
+
+\f
+;; Borrowed from http://postmomentum.ch/blog/201304/blog-on-emacs
+
+(defun sanityinc/split-window()
+  "Split the window to see the most recent buffer in the other window.
+Call a second time to restore the original window configuration."
+  (interactive)
+  (if (eq last-command 'sanityinc/split-window)
+      (progn
+        (jump-to-register :sanityinc/split-window)
+        (setq this-command 'sanityinc/unsplit-window))
+    (window-configuration-to-register :sanityinc/split-window)
+    (switch-to-buffer-other-window nil)))
+
+(global-set-key (kbd "<f7>") 'sanityinc/split-window)
+
+
+\f
+
+(defun sanityinc/toggle-current-window-dedication ()
+  "Toggle whether the current window is dedicated to its current buffer."
+  (interactive)
+  (let* ((window (selected-window))
+         (was-dedicated (window-dedicated-p window)))
+    (set-window-dedicated-p window (not was-dedicated))
+    (message "Window %sdedicated to %s"
+             (if was-dedicated "no longer " "")
+             (buffer-name))))
+
+(global-set-key (kbd "C-c <down>") 'sanityinc/toggle-current-window-dedication)
+
+
+\f
+
+(unless (memq window-system '(nt w32))
+  (require-package 'windswap)
+  (add-hook 'after-init-hook (apply-partially 'windmove-default-keybindings 'control))
+  (add-hook 'after-init-hook (apply-partially 'windswap-default-keybindings 'shift 'control)))
+
+
+(provide 'init-windows)
+;;; init-windows.el ends here
diff --git a/.emacs.d/lisp/init-yassnippet.el b/.emacs.d/lisp/init-yassnippet.el
new file mode 100644 (file)
index 0000000..285084b
--- /dev/null
@@ -0,0 +1,11 @@
+;;; init-yassnippet.el --- Snippets with yasnippet -*- lexical-binding: t -*-
+;;; Commentary:
+;;; Code:
+
+(require 'yasnippet)
+(add-hook 'prog-mode-hook 'yas-minor-mode)
+(add-hook 'text-mode-hook 'yas-minor-mode)
+(add-hook 'after-init-hook 'yas-global-mode)
+
+(provide 'init-yassnippet)
+;;; init-yassnippet.el ends here
diff --git a/.emacs.d/lisp/profile-dotemacs.el b/.emacs.d/lisp/profile-dotemacs.el
new file mode 100644 (file)
index 0000000..9d7bdbb
--- /dev/null
@@ -0,0 +1,200 @@
+;;; profile-dotemacs.el --- Profile your Emacs init file
+
+;; Copyright (C) 2010, 2012  David Engster
+
+;; Author: David Engster <dengste@eml.cc>
+
+;; This file is NOT part of GNU Emacs.
+
+;; 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, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This is to easily profile your Emacs init file (or any other
+;; script-like Emacs Lisp file, for that matter).
+
+;; It will go over all sexp's (balanced expressions) in the file and
+;; run them through `benchmark-run'.  It will then show the file with
+;; overlays applied in a way that let you easily find out which sexp's
+;; take the most time.  Since time is relative, it's not the absolute
+;; value that counts but the percentage of the total running time.
+;;
+;; * All other sexp's with a percentage greater than
+;;   `profile-dotemacs-low-percentage' will be preceded by a
+;;   highlighted line, showing the results from `benchmark-run'.
+;;   Also, the more 'reddish' the background of the sexp, the more
+;;   time it needs.
+
+;; * All other sexp's will be grayed out to indicate that their
+;;   running time is miniscule.  You can still see the benchmark
+;;   results in the minibuffer by hovering over the sexp with the
+;;   mouse.
+
+;; You can only benchmark full sexp's, so if you wrapped large parts
+;; of your init file in some conditional clause, you'll have to remove
+;; that for getting finer granularity.
+
+;;; Usage:
+
+;; Start emacs as follows:
+;;
+;;    emacs -Q -l <PATH>/profile-dotemacs.el -f profile-dotemacs
+;;
+;; with <PATH> being the path to where this file resides.
+
+;;; Caveats (thanks to Raffaele Ricciardi for reporting those):
+
+;; - The usual `--debug-init' for debugging your init file won't work
+;;   with profile-dotemacs, so you'll have to call
+;;   `toggle-debug-on-error', either on the commandline or at the
+;;   beginning of your init file.
+;; - `load-file-name' is nil when the init file is being loaded
+;;   by the profiler.  This might matter if you perform the
+;;   bulk of initializations in a different file.
+;; - Starting external shells like IELM or eshell in your init file
+;;   might mess with overlay creation, so this must not be done.
+
+;;; Download:
+
+;;  You can always get the latest version from
+;;       http://randomsample.de/profile-dotemacs.el
+
+;;; Code:
+
+(require 'thingatpt)
+(require 'benchmark)
+
+;; User variables
+
+(defvar profile-dotemacs-file "~/.emacs.d/init.el"
+  "File to be profiled.")
+
+(defvar profile-dotemacs-low-percentage 3
+  "Percentage which should be considered low.
+All sexp's with a running time below this percentage will be
+grayed out.")
+
+(defface profile-dotemacs-time-face
+  '((((background dark)) (:background "OrangeRed1"))
+    (t (:background "red3")))
+  "Background color to indicate percentage of total time.")
+
+(defface profile-dotemacs-low-percentage-face
+  '((((background dark)) (:foreground "gray25"))
+    (t (:foreground "gray75")))
+  "Face for sexps below `profile-dotemacs-low-percentage'.")
+
+(defface profile-dotemacs-highlight-face
+  '((((background dark)) (:background "blue"))
+    (t (:background "yellow")))
+  "Highlight face for benchmark results.")
+
+;; Main function
+
+(defun profile-dotemacs ()
+  "Load `profile-dotemacs-file' and benchmark its sexps."
+  (interactive)
+  (with-current-buffer (find-file-noselect profile-dotemacs-file t)
+    (setq buffer-read-only t) ;; just to be sure
+    (goto-char (point-min))
+    (let (start end results)
+      (while
+          (< (point)
+             (setq end (progn
+                         (forward-sexp 1)
+                         (point))))
+        (forward-sexp -1)
+        (setq start (point))
+        (add-to-list
+         'results
+         `(,start ,end
+                  ,(benchmark-run
+                    (eval (sexp-at-point)))))
+        (goto-char end))
+      (profile-dotemacs-show-results results)
+      (switch-to-buffer (current-buffer)))))
+
+;; Helper functions
+
+(defun profile-dotemacs-show-results (results)
+  "Show timings from RESULTS in current buffer."
+  (let ((totaltime (profile-dotemacs-totaltime results))
+        current percentage ov)
+    (while results
+      (let* ((current (pop results))
+             (ov (make-overlay (car current) (cadr current)))
+             (current (car (last current)))
+             (percentage (/ (+ (car current) (nth 2 current))
+                            totaltime))
+             col benchstr lowface)
+        (setq col
+              (profile-dotemacs-percentage-color
+               percentage
+               (face-background 'default)
+               (face-background 'profile-dotemacs-time-face)))
+        (setq percentage (round (* 100 percentage)))
+        (setq benchstr (profile-dotemacs-make-benchstr current))
+        (overlay-put ov 'help-echo benchstr)
+        (if (and (numberp profile-dotemacs-low-percentage)
+                 (< percentage profile-dotemacs-low-percentage))
+            (overlay-put ov 'face 'profile-dotemacs-low-percentage-face)
+          (overlay-put ov 'before-string
+                       (propertize benchstr
+                                   'face 'profile-dotemacs-highlight-face))
+          (overlay-put ov 'face
+                       `(:background ,col)))))
+    (setq ov (make-overlay (1- (point-max)) (point-max)))
+    (overlay-put ov 'after-string
+                 (propertize
+                  (format "\n-----------------\nTotal time: %.2fs\n"
+                          totaltime)
+                  'face 'profile-dotemacs-highlight-face))))
+
+(defun profile-dotemacs-totaltime (results)
+  "Calculate total time of RESULTS."
+  (let ((totaltime 0))
+    (mapc (lambda (x)
+            (let ((cur (car (last x))))
+              (setq totaltime (+ totaltime (car cur) (nth 2 cur)))))
+          results)
+    totaltime))
+
+(defun profile-dotemacs-percentage-color (percent col-begin col-end)
+  "Calculate color according to PERCENT between COL-BEGIN and COL-END."
+  (let* ((col1 (color-values col-begin))
+         (col2 (color-values col-end))
+         (col
+          (mapcar (lambda (c)
+                    (round
+                     (+ (* (- 1 percent) (nth c col1))
+                        (* percent (nth c col2)))))
+                  '(0 1 2))))
+    (format "RGB:%04x/%04x/%04x"
+            (car col)
+            (nth 1 col)
+            (nth 2 col))))
+
+(defun profile-dotemacs-make-benchstr (timings)
+  "Create descriptive benchmark string from TIMINGS."
+  (format
+   (concat
+    "<Percentage: %d ; "
+    "Time: %.2f ; "
+    "Number of GC: %d ; "
+    "Time for GC: %.2f>\n")
+   percentage
+   (car timings) (nth 1 timings) (nth 2 timings)))
+
+
+;; profile-dotemacs.el ends here
diff --git a/.emacs.d/lisp/publish.el b/.emacs.d/lisp/publish.el
new file mode 100644 (file)
index 0000000..02d6cdd
--- /dev/null
@@ -0,0 +1,61 @@
+;;; publish.el --- generate and publish my site -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021-2022 Eshel Yaron
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ox-publish)
+(require 'ox-html)
+(require 'htmlize)
+(require 'f)
+
+(setq org-export-with-section-numbers nil
+      org-export-with-toc             nil)
+
+(setq org-html-html5-fancy t
+      org-html-doctype     "html5")
+
+(setq org-html-head-include-default-style nil
+      org-html-head-include-scripts       nil)
+
+(setq org-html-htmlize-output-type 'css)
+
+(setq org-publish-project-alist
+      `(("index"
+         :base-directory "~/checkouts/eshelyaron.com/org"
+         :base-extension "org"
+         :exclude ".*"
+         :include ("index.org")
+         :publishing-directory "/ssh:root@107.173.25.133:/var/www/html"
+         :publishing-function org-html-publish-to-html
+         :html-head     "<link rel=\"stylesheet\" href=\"/style.css\" type=\"text/css\"/>"
+         :html-postamble ,(f-read-text "~/checkouts/eshelyaron.com/org/html_postamble.html"))
+        ("static"
+         :base-directory "~/checkouts/eshelyaron.com/org"
+         :base-extension "ico\\|css\\|jpg\\|gif\\|png\\|txt\\|pdf"
+         :recursive t
+         :publishing-directory "/ssh:root@107.173.25.133:/var/www/html"
+         :publishing-function org-publish-attachment)
+        ("eshelyaron.com" :components ("index" "static"))
+        ("index.local"
+         :base-directory "~/checkouts/eshelyaron.com/org"
+         :base-extension "org"
+         :exclude ".*"
+         :include ("index.org")
+         :publishing-directory "~/checkouts/eshelyaron.com/html"
+         :publishing-function org-html-publish-to-html
+         :html-head     "<link rel=\"stylesheet\" href=\"/style.css\" type=\"text/css\"/>"
+         :html-postamble ,(f-read-text "~/checkouts/eshelyaron.com/org/html_postamble.html"))
+        ("static.local"
+         :base-directory "~/checkouts/eshelyaron.com/org"
+         :base-extension "ico\\|css\\|jpg\\|gif\\|png\\|txt\\|pdf"
+         :recursive t
+         :publishing-directory "~/checkouts/eshelyaron.com/html"
+         :publishing-function org-publish-attachment)
+        ("eshelyaron.local" :components ("index.local" "static.local"))))
+
+
+(provide 'publish)
+;;; publish.el ends here
diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..ab50452
--- /dev/null
@@ -0,0 +1,23 @@
+/.emacs.d/.bookmarks.el
+/.emacs.d/.cache/
+/.emacs.d/.dap-breakpoints
+/.emacs.d/.last-package-update-day
+/.emacs.d/.lsp-session-v1
+/.emacs.d/.org-id-locations
+/.emacs.d/auto-save-list/
+/.emacs.d/cache/
+/.emacs.d/dtache.db
+/.emacs.d/eln-cache/
+/.emacs.d/elpa/
+/.emacs.d/eshell/
+/.emacs.d/forge-database.sqlite
+/.emacs.d/network-security.data
+/.emacs.d/projectile-bookmarks.eld
+/.emacs.d/projects
+/.emacs.d/recentf
+/.emacs.d/request/
+/.emacs.d/snippets/
+/.emacs.d/tramp
+/.emacs.d/transient/
+/.emacs.d/url/
+/.emacs.d/var/
diff --git a/.gitmodules b/.gitmodules
new file mode 100644 (file)
index 0000000..94d18c9
--- /dev/null
@@ -0,0 +1,3 @@
+[submodule ".emacs.d/checkouts/flymake-swi-prolog"]
+       path = .emacs.d/checkouts/flymake-swi-prolog
+       url = https://git.sr.ht/~eshel/flymake-swi-prolog