;;; init.el --- my emacs configuration  -*- lexical-binding: t; -*-

;;; Commentary:

;; (profiler-start 'cpu+mem)

;;; Getting started

(add-to-list 'load-path (expand-file-name (concat user-emacs-directory "site-lisp")))

(add-to-list 'exec-path "/home/noa/.config/Scripts")

(use-package use-package
  :custom
  (use-package-compute-statistics t)
  (use-package-enable-imenu-support t))

;; Give me stats on garbage collection and startup time
(add-hook 'emacs-startup-hook
	  #'(lambda ()
	      (message (format "Initialised in %s seconds with %s garbage collections." (emacs-init-time) gcs-done))))

;; keep the emacs directory clean
(use-package no-littering)

;;; Make a nice interface
(use-package tubthumping-theme
  :disabled t
  :load-path "~/Documents/Projects/Tubthumping/"
  :config
  (load-theme 'tubthumping t))

;; Using a proportional font is the right way to do things, but emacs is very old and comes from a time before the innovation of legibility.  As a result, there are some things that require a monospaced font, so i set one here.
(custom-set-faces
 '(default ((t (:family "Noto Sans Mono" :height 120))))
 '(variable-pitch ((t (:family "Noto Sans" :height 120))))
 '(fixed-pitch ((t (:family "Noto Sans Mono" :height 120))))
 )

(use-package face-remap
  :hook
  ((text-mode . variable-pitch-mode)
   (prog-mode . variable-pitch-mode)))

;; Use simplified not korean hanzi
(when (display-graphic-p)
  (dolist (charset '(han cjk-misc))
    (set-fontset-font t charset (font-spec :family "Noto Serif CJK SC"))))

;; Prioritise fsd and noto emoji over coloured variants
(when (and (display-graphic-p)
           (member "FSD Emoji" (font-family-list)))
  (set-fontset-font t 'emoji (font-spec :family "FSD Emoji") nil 'prepend))
(when (and (display-graphic-p)
           (member "Noto Emoji" (font-family-list)))
  (set-fontset-font t 'emoji (font-spec :family "Noto Emoji") nil 'append))

;; Nicer terminal emacs
(set-display-table-slot standard-display-table 'vertical-border (make-glyph-code ?│))
(setq mode-line-end-spaces nil)

(use-package xclip)
(unless (display-graphic-p) (xclip-mode 1))

;; Don't advertise gnu on startup
(setq inhibit-startup-echo-area-message "noa")  ;; #userfreedom

;; Make tooltip information appear consistently in the echo area
(use-package tooltip
  :custom (tooltip-mode nil))

;; startup.el does not provide itself, cannot be used with use-package
(setopt inhibit-startup-screen t)

(use-package mouse
  :custom
  (mouse-yank-at-point t)
  (mouse-drag-and-drop-region nil)
  (mouse-yank-at-point t)
  ;; Allow for slightly sloppier clicking.
  (mouse-prefer-closest-glyph t) ;; Emacs 30
  )

;; Shift click to select region with the mouse (https://christiantietze.de/posts/2022/07/shift-click-in-emacs-to-select/)
(global-set-key (kbd "S-<down-mouse-1>") #'mouse-set-mark)
;; Doesn't work great with a proportional font but could still be useful.
(global-set-key (kbd "C-S-<down-mouse-1>") #'mouse-drag-region-rectangle)

;;; Minibuffer

;; It is often useful to be able to run a command while i am already in the process of running a command in the minibuffer.  This is rarely two extended commands; usually it is completion.

(use-package savehist
  :custom
  (savehist-file "~/.config/emacs/savehist")
  (savehist-additional-variables
   '(kill-ring
     command-history
     set-variable-value-history
     custom-variable-history
     query-replace-history
     read-expression-history
     minibuffer-history
     read-char-history
     face-name-history
     bookmark-history
     file-name-history))
  :hook (after-init . savehist-mode))

(use-package mb-depth
  :hook (after-init . minibuffer-depth-indicate-mode))

(use-package vertico
  :hook (after-init . vertico-mode)
  :custom
  (vertico-resize nil) ;; don't shrink when there are less candidates
  ;; (vertico-group-format #("%s " 0 3 (face vertico-group-title))) ;; Don't put a vertical line across group titles
  )

(use-package vertico-directory
  :after vertico
  ;; If i type ~/ etc in a find-file prompt, get rid of the preceding directory names for a cleaner look.
  :hook (rfn-eshadow-update-overlay . vertico-directory-tidy))

;; Annotations for completing-read

;; Taken from configuration for the vertico stack:
;; Add prompt indicator to `completing-read-multiple'.
;; We display [CRM<separator>], e.g., [CRM,] if the separator is a comma.
(defun crm-indicator (args)
  (cons (format "[CRM%s] %s"
		(replace-regexp-in-string
		 "\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" ""
		 crm-separator)
		(car args))
	(cdr args)))
(advice-add #'completing-read-multiple :filter-args #'crm-indicator)

(use-package marginalia
  :defer t
  :hook (after-init . marginalia-mode)
  ;; :custom
  ;; (marginalia-mode t)
  )

;; Basic matches candidates with the same text before the point, and the text after the point as a substring.
;; Orderless takes any number of space separated components and displays candidates that much every component in any order.
;; I don't actually know if these make any difference when i've specified a different completion style.
(use-package minibuffer
  :custom
  (read-file-name-completion-ignore-case t))

(use-package orderless
  :after minibuffer
  :custom
  (completion-styles '(orderless basic))
  (completion-category-overrides '((file (styles basic partial-completion)))))

(use-package consult
  :defer t
  ;; :commands (consult-complete-in-region)
  :bind
  (
   ;; ([remap switch-to-buffer] . consult-buffer)
   ([remap yank-pop] . consult-yank-pop)
   ([remap goto-line] . consult-goto-line)
   ;; ([remap imenu] . consult-imenu)
   ;; ([remap info] . consult-info)
   ([remap repeat-complex-command] . consult-complex-command)
   ([remap bookmark-jump] . consult-bookmark)
   ("C-x C-r" . consult-recent-file)
   :map comint-mode-map
   ([remap comint-history-isearch-backward-regexp] . consult-history))
  ;; :custom
  ;; Use consult for completion at point
  ;; (completion-in-region-function 'consult-completion-in-region)
  )

;;; Dictionary
;; Emacs has built in support for interfacing with dictd.  With dictd and some dictionaries installed on debian, this works fine out of the box.
;; Unfortunately, dictionaries in this format tend to be hard wrapped and there isn't a lot of coverage outside of english
(use-package dictionary
  :defer t
  :custom
  (dictionary-search-interface nil))

;;; Offline web browsing

;; Despite the name, eww is a delight to use for text-heavy websites.
(use-package browse-url
  :defer t
  :custom
  (browse-url-browser-function 'noa/record-url)
  (browse-url-secondary-browser-function 'browse-url-default-browser))

(use-package shr
  :defer t
  :custom
  (shr-use-colors nil) ;; I like the colours i already have set
  (shr-max-width nil) ;; Don't insert hard linebreaks to wrap paragraphs
  (shr-bullet " • ")
  (shr-discard-aria-hidden t))

(use-package eww
  :defer t

  :custom
  ;; Better buffer naming for eww buffers.  See the help for a function which gives the page title and the url.
  (eww-auto-rename-buffer 'title))

;; Goto address mode makes urls and email address in a buffer clickable.  I want these clickable links to look like links, because that's what they are.  The two mouse face variables are what face is used on hover, which at the moment i ignore.  It might also be worth setting them to 'highlight.
(use-package goto-addr
  :hook (after-init . global-goto-address-mode))

(defvar noa/record-url-file "~/Documents/Library/urls")
(defun noa/record-url (url &rest args)
  "An alternative browser function that appends the url to a file.  We do not pay attention to any arguments."
  (write-region (concat url "\n") nil noa/record-url-file 'append))

;;; Programming

(use-package flymake
  :hook (prog-mode . flymake-mode))

;; If i write a script, i will always run chmod +x after saving it.  This command means i don't have to do that.
(add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p)

(use-package sly
  :disabled t
  :if (executable-find "sbcl")
  :ensure t
  :commands 'sly
  :custom ((inferior-lisp-program (executable-find "sbcl"))
           (common-lisp-hyperspec-root "file:///usr/share/doc/hyperspec/"))
  :mode ((rx (or ".lisp" ".cl") eos) . common-lisp-mode))

(use-package ediff
  :defer t
  :custom
  (ediff-window-setup-function 'ediff-setup-windows-plain)
  (ediff-split-window-function 'split-window-horizontally))

(use-package elastic-indent
  :disabled t
  :hook (prog-mode . elastic-indent-mode))

;; Change the width of tab characters within lines to make subsequent lines form a table-like layout.
(use-package elastic-table
  :disabled t
  :hook (prog-mode-hook . elastic-table-mode))

;; Indenting lisp with tabs is horrible.  H/t acdw
(defvar space-indent-modes '(emacs-lisp-mode
                             lisp-interaction-mode
                             lisp-mode
                             scheme-mode
                             python-mode)
  "Modes to indent with spaces, not tabs.")
(add-hook 'prog-mode-hook
          (defun indent-tabs-mode-maybe ()
            (setq indent-tabs-mode
                  (if (apply #'derived-mode-p space-indent-modes) nil t))))

;; Scroll along with text in compilation mode, and stop scrolling at the first error.
(use-package compile
  :defer t
  :custom
  (compilation-scroll-output 'first-error))

;;; Writing prose

;; Use abbrev as a simple autocorrect mode.  M-x list-abbrevs for stats.
;; Check  ~/.config/emacs/abbrev_defs to update any mistakes
(use-package abbrev
  :hook (text-mode . abbrev-mode))

(use-package flyspell
  :hook (text-mode . flyspell-mode)
  :custom
  (flyspell-abbrev-p t))

;; Unfill commands
(defun unfill-paragraph ()
  "Takes a multi-line paragraph and makes it into a single line of text."
  (interactive)
  (let ((fill-column (point-max)))
    (fill-paragraph nil)))
(global-set-key (kbd "M-Q") #'unfill-paragraph)

;;; Reading mail

;; I keep coming back to rmail, despite its many, many warts.
;; Currently i fetch mail into Spool.mbox with fdm, then rmail moves it into Inbox.mbox.
(use-package rmail
  :commands (rmail)
  :custom
  (rmail-primary-inbox-list '("~/Documents/Library/Mail.new/Spool.mbox"))
  (rmail-file-name "~/Documents/Library/Mail.new/Inbox.mbox")
  (rmail-user-mail-address-regexp
   (rx "noa@noa.pub"))
  (rmail-mime-prefer-html nil)
  (rmail-mime-attachment-dirs-alist '(("" "~/media")))
  (rmail-displayed-headers
   (rx bol (or "To" "Cc" "From" "Date" "Subject") ":"))
  (rmail-delete-after-output t)
  (rmail-default-file "~/Documents/Library/Mail/Archive.mbox")
  (mail-dont-reply-to-names rmail-user-mail-address-regexp)

  (rmail-display-summary nil)
  (rmail-redisplay-summary t)
  (rmail-summary-line-count-flag nil)

  ;; :hook
  ;; ((rmail-show-message . visual-line-fill-column-mode))
  )

;;; Sending mail

(use-package message
  :defer t
  :init
  (defun noa/message-default-headers ()
    (format "Fcc: ~/Documents/Library/Mail/outbox/%s.mbox"
            (format-time-string "%Y-%m")))

  :custom
  (message-default-headers #'noa/message-default-headers)
  (message-fill-column nil) ;; Don't enable auto-fill
  (user-full-name "noa")
  (user-mail-address "noa@noa.pub")
  (message-signature t)
  (message-signature-file "~/.config/signature")
  (message-send-mail-function 'message-send-mail-with-sendmail)
  (sendmail-program (executable-find "msmtpq"))
  (message-sendmail-extra-arguments '("--read-envelope-from"))
  (message-sendmail-envelope-from 'header)
  (message-kill-buffer-on-exit t)
  (message-sendmail-f-is-evil t)
  (message-forward-as-mime t)
  (message-interactive t)
  (message-auto-save-directory "~/Documents/Library/Mail/drafts"))

;;; Bibliography management
;; TODO: update this to fit with the new single org file notes system.  This way should be easier than the previous method i think.
(use-package ebib
  :defer t
  :custom
  (ebib-bibtex-dialect 'biblatex)
  (ebib-index-columns '(("Author/Editor" 40 t)
                        ("Year" 6 t)
                        ("Title" 50 t)
                        ("Entry Key" 40 t)))
  (ebib-file-associations '(("pdf" . "xdg-open") ("ps" . "gv"))))

(use-package citar
  :defer t
  :commands (citar-insert-citation citar-open-files citar-open-notes)
  :custom
  (citar-bibliography '("~/Documents/Library/References.bib"))
  (citar-library-paths '("~/Documents/Library/Papers"))
  (citar-notes-paths '("~/Documents/Notes"))
  )
(use-package citar-org
  :after oc
  :custom
  (org-cite-insert-processor 'citar)
  (org-cite-follow-processor 'citar)
  (org-cite-activate-processor 'citar))

(use-package bibtex
  :defer t
  :custom
  (bibtex-dialect 'biblatex)
  (bibtex-entry-format '(opts-or-alts
                         page-dashes
                         required-fields
                         numerical-fields
                         whitespace
                         last-comma
                         delimiters
                         unify-case
                         sort-fields))
  (bibtex-field-delimiters 'braces)
  (bibtex-entry-delimiters 'braces)
  ;; Use one name, appending ETAL if there is more than one author
  ;; The name should be all caps
  (bibtex-autokey-names 1)
  (bibtex-autokey-name-case-convert-function 'upcase)
  (bibtex-autokey-additional-names "ETAL")
  ;; Follow this with the full year
  ;; Probably don't need more than two digits actually
  (bibtex-autokey-name-year-separator "-")
  (bibtex-autokey-year-length 4)
  ;; Follow this with initials of the title
  (bibtex-autokey-year-title-separator "-")
  (bibtex-autokey-titlewords t)
  (bibtex-autokey-titleword-length -1) ;; One character
  (bibtex-autokey-titleword-separator "")
  (bibtex-autokey-titleword-case-convert-function 'upcase))

(use-package biblio
  :disabled t
  :ensure t
  :defer t
  :custom
  (biblio-bibtex-use-autokey t)
  (biblio-download-directory "~/Documents/Library/Papers"))

;;; Taking notes
(use-package org
  :defer t
  :init

  :custom
  (org-agenda-files '("~/Documents/Notes.org" "~/Documents/Notes/"))
  (org-replace-disputed-keys t)
  (org-support-shift-select 'always) ;; Still refuses to fix on timestamps :/
  (org-log-done 'time)
  (org-pretty-entities t)
  (org-startup-with-inline-images t)
  (org-image-actual-width '(300))
  (org-ellipsis " [+]")
  (org-insert-heading-respect-content t)
  (org-fontify-done-headline nil)
  (org-fontify-todo-headline nil)
  (org-fontify-whole-heading-line t)
  (org-src-fontify-natively t)
  (org-src-tab-acts-natively t)
  (org-edit-src-content-indentation 0)
  (org-use-sub-superscripts '{})

  :custom-face
  (org-table ((t (:inherit fixed-pitch))))
  (org-date ((t (:inherit fixed-pitch :underline t))))

  :hook ((org-mode . font-lock-mode))

  )

(add-hook 'text-mode-hook (lambda ()
                            (setq-local line-spacing 0.1)))

(use-package oc
  :after org
  :custom
  (org-cite-global-bibliography '("~/Documents/Library/References.bib"))
  (org-cite-export-processors '((beamer csl)
                                (latex csl)
                                (t csl))))
(use-package oc-csl
  :after oc
  :custom
  (org-cite-csl-styles-dir "~/Documents/Library/Citations styles"))

;; Not working how i want
(use-package org-capture
  :bind ("C-c c" . org-capture)
  :custom
  (org-capture-templates
   '(("d" "Today's diary" entry
      (file+headline "~/Documents/Notes.org" "Diary")
      "** %u\n%?"))))

;; See https://llazarek.github.io/blog/2018/07/organization-with-org-mode.html
;; for configuring the org agenda

;; Experimental website generator
(use-package ox-hugo
  :disabled t
  :ensure t
  :after ox)

;; Markdown
(use-package markdown-mode
  :mode ("\\.\\(?:md\\|markdown\\|mkd\\|mdown\\|mkdn\\|mdwn\\)\\'" . markdown-mode)
  :custom
  (markdown-disable-tooltip-prompt t) ; When inserting a link, only prompt for url and link text
  (markdown-enable-html nil) ; I don't believe markdown should have html
  (markdown-hide-urls t) ; Make inline urls look a bit neater
  (markdown-url-compose-char ?~)
  (markdown-max-image-size '(640 . 480))

  ;; :hook ((markdown-mode . noa/set-buffer-name-to-markdown-title))
  )

;;; System administration

(use-package proced
  :defer t
  :custom
  (proced-auto-update-flag t)
  (proced-auto-update-interval 1)
  (proced-enable-color-flag nil)
  (proced-show-remote-processes t))

;;; Completion

;; Some settings for nicer completion with the default emacs completion buffer.  I don't use this, because i use vertico.
;; (setopt completion-auto-help 'lazy
;;         completion-auto-select 'second-tab
;;         completion-show-help nil
;;         completions-sort nil
;;         completions-header-format nil)

;; Completion styles
;; When given a prompt to select from a list of candidates, there are quite a lot of things we can tweak to improve the experience.

;;; File management

(use-package consult-recoll
  :bind ("<menu>" . consult-recoll)
  :custom
  (consult-recoll-inline-snippets nil)
  (consult-recoll-group-by-mime nil))

(use-package dired
  :defer t
  :custom
  (dired-recursive-deletes 'always) ;; Don't ask me things
  (dired-recursive-copies 'always) ;; Don't ask me things
  (dired-dwim-target t) ;; Synergy between two dired windows
  ;; I have quite a bit of storage and also make bad decisions regularly
  ;; People who have used computers in the last forty years or so will likely be familiar with this innovation.
  (delete-by-moving-to-trash t)

  ;; -l is required by dired
  ;; -a to also show dotfiles
  ;; -v to sort numbers properly
  ;; -F to visually distinguish different types of file
  ;; -h for human readable file sizes
  ;; I won't explain the meaning of the long flag.
  (dired-listing-switches "-alvFh --group-directories-first")

  ;; By default, don't show dired details
  :hook ((dired-mode . dired-hide-details-mode)
         (dired-mode . hl-line-mode))
  )

;; Show the recursive size of directories
(use-package dired-du
  :disabled t
  :hook (dired-mode . dired-du-mode)
  :after dired
  :custom
  (dired-du-size-format t))

(use-package recentf
  :hook (after-init . recentf-mode)
  :custom
  (recentf-max-menu-items 50))

;; Remember my position in files
(use-package saveplace
  :hook (after-init . save-place-mode))

;;; Window and buffer navigation

(use-package isearch
  :bind (:map isearch-mode-map
              ("<return>" . noa/isearch-done-goto-start) ; always put point at the beginning of the match
              ("C-g" . isearch-cancel) ; always quit on C-g
              ("C-o" . isearch-occur))
  :init (defun noa/isearch-done-goto-start (&optional nopush edit)
          "End isearch at the start of the match."
          (interactive)
          (funcall #'isearch-done nopush edit)
          (when isearch-forward (goto-char isearch-other-end)))
  :custom
  (isearch-lax-whitespace t)
  (isearch-lazy-count t)
  (isearch-allow-motion t)
  (isearch-repeat-on-direction-change t)
  (isearch-wrap-pause 'no))

(use-package avy
  :bind (("M-j" . avy-goto-char-timer)
	 :map isearch-mode-map
	 ("M-j" . avy-isearch))
  :custom
  (avy-keys (number-sequence ?a ?z))
  (avy-timeout-seconds 0.2))

;; Make window management commands easier to press
(use-package ace-window
  :bind ([remap other-window] . ace-window))

;; Better buffer naming
(use-package uniquify
  :custom
  (uniquify-after-kill-buffer-p t)
  (uniquify-buffer-name-style 'forward)
  (uniquify-ignore-buffers-re "^\\*")
  (uniquify-separator "/"))

;;; Embark

(use-package embark
  :bind
  (("C-." . embark-act)
   ([remap describe-bindings] . embark-bindings))

  :init
  (setq prefix-help-command #'embark-prefix-help-command))

(use-package embark-consult
  :after (embark consult)
  :hook
  (embark-collect-mode . consult-preview-at-point-mode))

;;; Reading pdfs and epub files

(use-package pdf-tools
  :when (display-graphic-p)
  :magic ("%PDF" . pdf-view-mode)
  :config
  (pdf-tools-install :no-query))

;;; Music

(use-package emms
  :disabled t
  :config
  (require 'emms-setup)
  (require 'emms-info-metaflac)
  (require 'emms-info-mp3info)
  (require 'emms-info-ogginfo)
  (emms-all)
  (emms-default-players)
  (setq emms-source-file-default-directory "~/Music/")
  (setq emms-browser-covers 'emms-browser-cache-thumbnail-async)
  (setq emms-playlist-default-major-mode 'emms-playlist-mode)
  (setq emms-track-description-function 'emacs-init/emms-track-description)
  (add-to-list 'emms-info-functions 'emms-info-libtag)
  (add-to-list 'emms-info-functions 'emms-info-mp3info)
  (add-to-list 'emms-info-functions 'emms-info-ogginfo)
  (global-set-key (kbd "C-c e p") 'emms-playlist-mode-go)
  (global-set-key (kbd "C-c e r") 'emms-toggle-repeat-playlist)
  (global-set-key (kbd "C-c e s") 'emms-toggle-random-playlist))

;;; Useful functions
(defun noa/yank-buffer-file-name ()
  (interactive)
  (when (buffer-file-name)
    (kill-new (file-name-nondirectory (buffer-file-name)))))

;; Insert date and time at point
;; Sometimes it's useful to be able to add a timestamp.  I use this for notes.  Use the same binding as notepad.exe.
(defun noa/insert-date (&optional time)
  "Insert the current date into the buffer.
With prefix argument TIME, also add the current time."
  (interactive "P")
  (if time
      (insert (format-time-string "[%Y-%m-%d %H:%M]"))
    (insert (format-time-string "[%Y-%m-%d]"))))
(defun noa/insert-date-time ()
  (interactive)
  (noa/insert-date t))

(global-set-key (kbd "<f5>") 'noa/insert-date-time)

(defun snarf-song (url)
  (interactive "sYoutube url:")
  (async-shell-command
   (concat "yt-dlp -x --audio-format=mp3 -o "
           (shell-quote-argument "~/media/music/%(title)s [%(id)s].%(ext)s")
           " "
           (shell-quote-argument url))))

;;; Tramp
(use-package tramp
  :defer t
  :custom
  (tramp-inline-compress-start-size 1000)
  (tramp-verbose 3))
;; (add-to-list 'tramp-remote-path 'tramp-own-remote-path)

;;; Window management
;; Don't override display actions when i manually initiate a buffer switch.
(use-package window
  :custom
  ;; My computer has a small screen, so i find that it's more beneficial for me to split the frame into columns, so i get more context.  However, splitting in this way only gives me a (window-width) of 61, so emacs will always split into vertically stacked windows.  By setting this to 80, the first split should always be vertical.
  (split-width-threshold 80)
  (switch-to-buffer-obey-display-actions t)
  ;; C-l from top to bottom
  (recenter-positions '(top middle bottom)))

(use-package frame
  :hook (after-init . window-divider-mode)
  :custom
  (window-divider-default-right-width 1)
  (window-divider-default-bottom-width 1)
  (window-divider-default-places t))

;;; Unsorted

;; Update the calendar.  We want weeks to start on a monday, the first day of the week.  Holidays should be highlighted, and the date format should put the year first.
(use-package calendar
  :defer t
  :custom
  (calendar-week-start-day 1)
  (calendar-date-style 'iso)

  :config
  ;; Ensure the calendar always displays at the bottom of the screen, rather than wrapping weirdly and looking bad when it shows up in a side window.
  (add-to-list 'display-buffer-alist
               '("\\*Calendar\\*"
                 (display-buffer-in-side-window)
                 (side . bottom))))

;; Squeeze text into a more legible sliver.
(use-package visual-fill-column
  :custom
  (visual-fill-column-enable-sensible-window-split t)
  (visual-fill-column-fringes-outside-margins nil) ; Keep fringes on the inside so relevant icons are in the right place
  (visual-fill-column-center-text t)
  :hook
  ((text-mode . visual-fill-column-mode)
   (eww-after-render . visual-line-fill-column-mode))
  )

;; (advice-add 'text-scale-adjust :after #'visual-fill-column-adjust)

;; Doesn't indent nicely with proportional fonts
;; (use-package adaptive-wrap :ensure t)
;; (add-hook 'visual-fill-column-mode-hook #'visual-wrap-prefix-mode)

(use-package simple
  :hook ((text-mode . visual-line-mode)
         (after-init . auto-save-mode))
  :bind ([remap kill-buffer] . kill-current-buffer)
  :custom
  (save-interprogram-paste-before-kill t)
  (kill-ring-max 25)
  ;; Hide commands in M-x which do not work in the current mode.
  (read-extended-command-predicate 'command-completion-default-include-p)
  ;; My brain is not ready for advanced emacs undo
  (undo-no-redo t)
  :bind (("C-z" . undo)
         ("C-S-z" . undo-redo)))

(use-package help
  :defer t
  :custom
  ;; When opening source files from a help window, use the same window
  (help-window-keep-selected t))

(use-package emacs
  :custom
  (window-combination-resize t)
  (window-resize-pixelwise t)
  (frame-resize-pixelwise t)
  (shell-file-name "/bin/sh")
  (completion-ignore-case t)
  (read-buffer-completion-ignore-case t)
  ;; yes-or-no-p uses y-or-no-p, and read-answer accepts single key press answers
  (use-short-answers t)
  (history-length 250)
  ;; Use a bar cursor and blink it and don't stop blinking it.
  (cursor-type 'bar)
  ;; Support opening new minibuffers from inside existing minibuffers.
  (enable-recursive-minibuffers t)
  ;; Whether to drop into the debugger on any error.  This seems cool, but in practice is a bit annoying.
  (debug-on-error nil)
  (create-lockfiles nil)
  (auto-save-interval 6)  ;; every six keystrokes
  (auto-save-timeout 5) ;; every 5 seconds
  (auto-save-no-message t)
  ;; Always give me a line of text when i'm near the edges of the screen
  (scroll-margin 2))

(use-package files
  :custom
  (view-read-only t)
  (confirm-kill-emacs 'y-or-n-p)
  ;; We are on a unix system, so it makes sense to end files in the unix system way.  I'm surprised this isn't the default.
  (require-final-newline t)

  ;; This behaviour changes how we visit symlinks.
  (find-file-visit-truename t)

  (remote-file-name-inhibit-locks t)
  (remote-file-name-inhibit-auto-save t)
  (remote-file-name-inhibit-auto-save-visited t)
  (backup-directory-alist '(("." . "~/.config/emacs/backups/")))
  (make-backup-files nil)
  (backup-by-copying t)
  (version-control t)
  ;; this will auto save to the current file
  (auto-save-visited-mode t)
  (auto-save-visited-interval 0.1)
  (save-silently t) ;; don't message when saving
  )

;; Disable disabled commands
(setq disabled-command-function nil)

;; Don't save changes in the customize interface
(use-package cus-edit
  :custom
  (custom-file (make-temp-file "custom")))

;; Emacs server
;; (unless (server-running-p) (server-start)))

;; Better support for long lines.
(use-package so-long
  :hook (after-init . global-so-long-mode))

;; Automatically revert buffers when they change on disk.  This doesn't apply to tramp.
(use-package autorevert
  :hook (after-init . global-auto-revert-mode)
  :custom
  (global-auto-revert-non-file-buffers t))

(use-package vc-hooks
  :custom
  (vc-follow-symlinks 'ask))

;; Zap up to char
(global-set-key (kbd "M-z") 'zap-up-to-char)

(setenv "PAGER" "cat")
(setenv "TERM" "dumb")
(setenv "NO_COLOR")
(setenv "GPG_AGENT_INFO" nil)

;;; Cleanup

;; (profiler-stop)