;;; init.el --- Emacs configuration

;;; Commentary:

;; Making Emacs relatively usable on a MacBook.

;;; Code:

(tool-bar-mode -1)
(toggle-scroll-bar -1)

(setq tab-width 4)
(setq indent-tabs-mode nil)
(setq-default indent-tabs-mode nil)

(turn-on-font-lock)

(setq inhibit-splash-screen t)
(setq inhibit-startup-screen t)
(setq initial-scratch-message nil)
(setq initial-major-mode 'text-mode)

(setq make-backup-files nil)

;; Automatically reload files edited elsewhere:
(setq global-auto-revert-mode t)

;; Wrap lines please:
(global-visual-line-mode t)

(setq gc-cons-threshold 100000000)

;; Nicer font:
(set-face-attribute 'default nil :family "Hack")

(when (eq system-type 'darwin)
  ;; Let's disable the right "Alt" key so I can still
  ;; use my German keyboard for entering German letters
  ;; on a Mac.
  (setq ns-right-alternate-modifier nil))

;; Remember where we are:
(desktop-save-mode t)

;; Don't keep open buffers though:
;; -- This will break Circe - disable for now.
;;(add-hook 'kill-emacs-hook (lambda () (desktop-clear)))

;; Stop chatting:
(defalias 'yes-or-no-p 'y-or-n-p)

;; Show the current line:
(global-hl-line-mode t)

;; Make window resizes undoable:
(when (fboundp 'winner-mode)
  (winner-mode 1))


;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; PACKAGE PREPARATION:
;;;;;;;;;;;;;;;;;;;;;;;;;;

(require 'package)
(add-to-list 'package-archives
	     '("melpa" . "https://melpa.org/packages/") t)

;; Initialize MELPA packages:
(when (< emacs-major-version 27)
  (package-initialize))

(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))

(require 'use-package)


;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; BUILT-IN PACKAGES:
;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Perl programming:
;; Use the C Perl mode (may be better than the default one).
(defalias 'perl-mode 'cperl-mode)

;; Gnus preparation: Make it faster and nicer looking.
;; (Let's keep the account configuration in .gnus.el though.)
(use-package gnus
  :config
  (setq gnus-always-read-dribble-file t)
  (setq gnus-read-active-file t)
  (gnus-add-configuration '(article (vertical 1.0 (summary .35 point) (article 1.0)))))

(use-package gnus-async
  :after gnus
  :config
  (setq gnus-asynchronous t)
  (setq gnus-use-article-prefetch 15))

;; org-mode improvements:
(use-package org
  :config
  ;; Better HTML export.
  (setq org-html-coding-system 'utf-8-unix)
  
  ;; Better inline code blocks.
  (setq org-src-fontify-natively t)
  (setq org-src-tab-acts-natively t))


;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; 3rd PARTY PACKAGES:
;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Keep my packages up-to-date:
(use-package auto-package-update
  :ensure t
  :config
  (setq auto-package-update-interval 4) ;; ... days
  (setq auto-package-update-delete-old-versions t)
  (setq auto-package-update-hide-results t)
  (auto-package-update-maybe))

;; Some platforms (cough) don't update Emacs's path.
;; Make them.
(when (eq system-type 'darwin)
  (use-package exec-path-from-shell
    :ensure t
    :init
    (setq exec-path-from-shell-check-startup-files nil)
    (exec-path-from-shell-initialize)))

;; Multiple cursors:
(use-package multiple-cursors
  :ensure t
  :config
  (global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines))

;; Asynchronous Emacs:
(use-package async
  :ensure t)

;; Gopher:
(use-package gopher
  :ensure t)

;; Support org-mode import from a website:
(use-package org-web-tools
  :ensure t)

;; Support my blog as well:
(use-package org2blog
  :ensure t
  :config
  (setq org2blog/wp-show-post-in-browser t)
  :init
  ;; Keep the log-in data out of the public eye:
  (load-file "~/.emacs.d/org2blog-config.el"))

;; Preview HTML:
(use-package org-preview-html
  :ensure t
  :after org
  :init
  (add-hook 'org-mode-hook #'org-preview-html-mode))

;; Web development:
(use-package web-mode
  :ensure t
  :init
  (add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.php\\'" . web-mode)))

;; RSS feed reader with some extras:
(use-package elfeed
  :ensure t)

(use-package elfeed-goodies
  :ensure t
  :after elfeed
  :init
  (elfeed-goodies/setup))

;; Hook elfeed into Newsblur:
(use-package elfeed-protocol
  :ensure t
  :after elfeed
  :init
  ;; Keep the log-in data out of the public eye:
  (elfeed-protocol-enable)
  (load-file "~/.emacs.d/elfeed-config.el"))

;; A less shitty modeline:
(use-package doom-modeline
  :ensure t
  :init (doom-modeline-mode 1))

;; A less shitty package manager:
(use-package paradox
  :ensure t
  :config
  (setq paradox-execute-asynchronously t)
  :init
  (paradox-enable))

;; Markdown support:
(use-package markdown-mode
  :ensure t
  :commands (markdown-mode gfm-mode)
  :mode (("README\\.md\\'" . gfm-mode)
         ("\\.md\\'" . markdown-mode)
         ("\\.markdown\\'" . markdown-mode))
  :init
  (when (executable-find "multimarkdown") (setq markdown-command "multimarkdown")))

;; Use ripgrep instead of grep (if applicable).
(when (executable-find "rg")
  (use-package rg
    :ensure t
    :init
    (rg-enable-default-bindings)))
  
;; Project-related functionalities:
(use-package projectile
  :ensure t
  :init
  (projectile-mode +1)
  (define-key projectile-mode-map (kbd "s-p") 'projectile-command-map)
  (define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map))

;; Syntax checking:
(use-package flycheck
  :ensure t
  :config
  (add-hook 'after-init-hook #'global-flycheck-mode))

;; Enable some icons throughout Emacs:
(use-package all-the-icons
  :ensure t)

(use-package all-the-icons-dired
  :after all-the-icons
  :config
  (add-hook 'dired-mode-hook 'all-the-icons-dired-mode))

(use-package all-the-icons-gnus
  :after all-the-icons
  :init
  (all-the-icons-gnus-setup))

;; Better regexp search&replace:
(use-package visual-regexp
  :ensure t)

(use-package visual-regexp-steroids
  :ensure t
  :after visual-regexp
  :config
  (define-key global-map (kbd "C-c r") 'vr/replace)
  (define-key global-map (kbd "C-c q") 'vr/query-replace)
  (define-key global-map (kbd "C-c m") 'vr/mc-mark))

;; Lisp programming:
;; Use SLY as a CL subsystem.
(use-package sly
  :ensure t
  :config
  (when (eq system-type 'darwin)
    ;; Requires SBCL from MacPorts.
    (setq inferior-lisp-program "/opt/local/bin/sbcl")))

;; Go programming:
;; Install and set up the Go mode.
(use-package go-mode
  :ensure t
  :config
  (progn
    (unless (member "/opt/local/go/bin" (split-string (getenv "PATH") ":"))
      (setenv "PATH" (concat "/opt/local/go/bin:" (getenv "PATH"))))
    (setenv "GOPATH" (concat (getenv "HOME") "/go"))
    (setq gofmt-command (concat (getenv "GOPATH") "/bin/goimports"))))

;; Language Server Protocol:
(use-package lsp-mode
  :ensure t
  :commands (lsp lsp-deferred)
  :config
  (setq lsp-enable-snippet nil)
  :hook ((go-mode . lsp-deferred)
	 (perl-mode . lsp-deferred)))

(defun lsp-go-install-save-hooks ()
  "Install LSP hooks."
  (add-hook 'before-save-hook #'lsp-format-buffer t t)
  (add-hook 'before-save-hook #'lsp-organize-imports t t))
(add-hook 'go-mode-hook #'lsp-go-install-save-hooks)
(add-hook 'perl-mode-hook #'lsp-go-install-save-hooks)

(use-package lsp-ui
  :ensure t
  :commands lsp-ui-mode)

;; Company auto-completion for code:
(use-package company
  :ensure t
  :config
  (setq company-idle-delay 0)
  (setq company-minimum-prefix-length 1))

(use-package company-lsp
  :ensure t
  :commands company-lsp
  :after company
  :config
  (setq company-backends
        ;; Let's keep company-mode unobtrusive in most cases.
        (quote
         (company-lsp company-bbdb company-xcode company-cmake company-capf company-files
                      (company-dabbrev-code company-gtags company-etags company-keywords)))))

;; Counsel auto-completion for commands:
(use-package counsel
  :ensure t
  :after ivy
  :config (counsel-mode))

;; Ivy for most interactive stuff:
(use-package ivy
  :ensure t
  :defer 0.1
  :diminish
  :bind (("C-c C-r" . ivy-resume)
         ("C-x B" . ivy-switch-buffer-other-window))
  :custom
  (ivy-count-format "(%d/%d) ")
  (ivy-use-virtual-buffers t)
  (ivy-virtual-abbreviate (quote full))
  :config (ivy-mode))

(use-package ivy-rich
  :ensure t
  :after ivy
  :config
  (ivy-rich-mode 1)
  (setcdr (assq t ivy-format-functions-alist) #'ivy-format-function-line))

;; With icons:
(use-package all-the-icons-ivy-rich
  :ensure t
  :after ivy-rich
  :init
  (all-the-icons-ivy-rich-mode t))

;; Swiper for searching:
(use-package swiper
  :ensure t
  :after ivy
  :bind (("C-s" . swiper)
	 ("C-r" . swiper)))

;; Smart parentheses:
(use-package smartparens
  :ensure t
  :config
  (require 'smartparens-config)
  :init
  (smartparens-global-mode t))

;; Version Control enhancements:
(use-package darcsum
  :ensure t)

(use-package vc-fossil
  :ensure t
  :config
  (add-to-list 'vc-handled-backends 'Fossil t))

;; IRC:
(use-package circe
  :ensure t
  :commands (circe circe-set-display-handler)
  :config
  (enable-circe-color-nicks)
  (setq circe-reduce-lurker-spam t
        lui-time-stamp-position 'right-margin
        lui-time-stamp-format "%H:%M"
        circe-format-say "{nick:-16s} {body}"
        circe-format-self-say "<{nick:-16s}> {body}")
  :init
  ;; Again, keep the log-in data private:
  (load-file "~/.emacs.d/circe-config.el"))


;; Nicer theme:
(use-package nofrils-acme-theme
  :ensure t
  :init
  (load-theme 'nofrils-acme t))



(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.
 '(canlock-password "5e5c6fd080d6c0bce2d09b8ec6e3693c1a63c654")
 '(ivy-count-format "(%d/%d) ")
 '(ivy-use-virtual-buffers t)
 '(ivy-virtual-abbreviate (quote full))
 '(package-selected-packages
   (quote
    (web-mode lsp-mode visual-regexp-steroids vc-fossil use-package smartparens sly semi paradox org2blog org-web-tools org-preview-html nofrils-acme-theme nadvice multiple-cursors mood-line lsp-ui gopher go-mode gh flycheck exec-path-from-shell elfeed-protocol elfeed-goodies doom-modeline darcsum counsel company-lsp circe auto-package-update async all-the-icons-ivy-rich all-the-icons-gnus all-the-icons-dired))))
(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.
 )

(provide 'init)
;;; init.el ends here
