#+TITLE: EMACS Configuration.
#+AUTHOR: ayham
#+EMAIL: me@ayham.xyz

* Configure =use-package=

Always compile the packages, and use the newest version available.

#+BEGIN_SRC emacs-lisp
  (require 'use-package-ensure)
  ;;(use-package-always-ensure t)
  (use-package auto-package-update
    :ensure t
    :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 general :ensure t)
#+END_SRC

* Configure exec-path
#+BEGIN_SRC emacs-lisp
  (use-package exec-path-from-shell
    :ensure t
    :config (exec-path-from-shell-initialize))
#+END_SRC

* UI Preferences
** Tweak EMACS' window
   
Disable menu, scrollbar and minibuffer scrollbar; Enable hl-line-mode.

#+BEGIN_SRC emacs-lisp
  (if (display-graphic-p)
      (progn
        (tool-bar-mode -1)
        (menu-bar-mode -1)
        (scroll-bar-mode -1)))
  (set-window-scroll-bars (minibuffer-window) nil nil)
  (global-hl-line-mode 1)
  (defalias 'yes-or-no-p 'y-or-n-p)
#+END_SRC

Bind frame title to the name of the current project.

#+BEGIN_SRC emacs-lisp
  (setq frame-title-format '((:eval (projectile-project-name))))
#+END_SRC

Disable stuff

#+BEGIN_SRC emacs-lisp
  (setq inhibit-startup-message t) ;; replaced afterwards
  (setq ring-bell-function 'ignore)
#+END_SRC
   
UTF-8

#+BEGIN_SRC emacs-lisp
  (setq locale-coding-system 'utf-8)
  (set-terminal-coding-system 'utf-8)
  (set-keyboard-coding-system 'utf-8)
  (set-selection-coding-system 'utf-8)
  (prefer-coding-system 'utf-8)
#+END_SRC

** Load theme
   
Set fonts.
#+BEGIN_SRC emacs-lisp
  (add-to-list 'default-frame-alist '(font . "Iosevka" ))
  (set-face-attribute 'default t :font "Iosevka" )
#+END_SRC
   
Use =modus-vivendi= theme.

#+BEGIN_SRC emacs-lisp
  (use-package modus-themes :ensure t)
  (require 'modus-themes)

  ;; Add all your customizations prior to loading the themes
  (setq modus-themes-italic-constructs t
        modus-themes-bold-constructs nil
        modus-themes-region '(bg-only no-extend))

  ;; Load the theme files before enabling a theme
  ;;(modus-themes-load-themes)

  ;; Load the theme of your choice:
  ;;(modus-themes-load-vivendi) ;; OR (modus-themes-load-vivendi)

  (define-key global-map (kbd "<f5>") #'modus-themes-toggle)
#+END_SRC

Setup icons.

#+BEGIN_SRC emacs-lisp
  (use-package all-the-icons
    :ensure t
    :init)

  (use-package all-the-icons-dired
    :ensure t
    :init (add-hook 'dired-mode-hook 'all-the-icons-dired-mode))

  (use-package all-the-icons-ibuffer
    :ensure t
    :init (all-the-icons-ibuffer-mode 1))
#+END_SRC

** Load modeline

Spaceline.

#+BEGIN_SRC emacs-lisp
  (use-package spaceline
    :ensure t
    :config
    (require 'spaceline-config)
    (setq powerline-default-separator (quote arrow))
    (spaceline-spacemacs-theme))
#+END_SRC

** Environment specific configuration
*** =ORG-mode= Environment

Replace =ORG-mode= ellipsis with a downward arrow.

#+BEGIN_SRC emacs-lisp
  (setq org-ellipsis "↲")
  (setq org-indent-mode t)
  (setq org-startup-indented t)
#+END_SRC

* Basic Configuration

Use firefox

#+BEGIN_SRC emacs-lisp
  (setenv "BROWSER" "librewolf")
#+END_SRC

Change alt-key to super-key

#+BEGIN_SRC emacs-lisp
  (setq x-super-keysym 'meta)
#+END_SRC

Enable relative line numbering.

#+BEGIN_SRC emacs-lisp
  (setq display-line-numbers-type 'relative)

  (defcustom display-line-numbers-exempt-modes
    '(eshell-mode shell-mode term-mode ansi-term-mode org-mode)
    "Major modes on which to disable line numbers."
    :group 'display-line-numbers
    :type 'list
    :version "green")

  (defun display-line-numbers--turn-on ()
    "Turn on line numbers except for certain major modes.
    Exempt major modes are defined in `display-line-numbers-exempt-modes'."
    (unless (or (minibufferp)
                (member major-mode display-line-numbers-exempt-modes))
      (display-line-numbers-mode)))
  (global-set-key [f4] 'display-line-numbers-mode)
  (global-display-line-numbers-mode)
#+END_SRC

Increase the garbage collector threshold, to speed up some operations.
    
#+BEGIN_SRC emacs-lisp
  (setq gc-cons-threshold 20000000)
#+END_SRC

Treat CamelCaseSubWords as seperate words. 

#+BEGIN_SRC emacs-lisp
  (add-hook 'prog-mode-hook 'subword-mode)
#+END_SRC

If a file starts with #!, make it executable.
 
#+BEGIN_SRC emacs-lisp
  (add-hook 'after-save-hook 'executable-make-buffer-file-executable-if-script-p)
#+END_SRC
 
If saving a file in a directory doesn't exist, offer to create the parent directories recursively.

#+BEGIN_SRC emacs-lisp
  (add-hook 'before-save-hook
            (lambda ()
              (when buffer-file-name
                (let ((dir (file-name-directory buffer-file-name)))
                  (when (and (not (file-exists-p dir)) y-or-n-p (format "Directory %s does not exist, Create it?" dir))
                    (make-directory dir t ))))))
#+END_SRC

Require having a new line.

#+BEGIN_SRC emacs-lisp
  (setq require-final-newline t)
#+END_SRC

Make file sizes human-readable to dired buffers.

#+BEGIN_SRC emacs-lisp
  (setq-default dired-listing-switches "-alh")
#+END_SRC

Refresh buffer when the file is changed, stoping buffers and file getting out of sync.

#+BEGIN_SRC emacs-lisp
  (global-auto-revert-mode t)
#+END_SRC

When pressing the middle mouse button, paste where the curser is rather than where the mouse is.

#+BEGIN_SRC emacs-lisp
  (setq mouse-yank-at-point 1)
#+END_SRC

Better increase and decrease text scale.

#+BEGIN_SRC emacs-lisp
  (global-set-key  (kbd "C-+") 'text-scale-increase)
  (global-set-key (kbd "C--") 'text-scale-decrease)
#+END_SRC

Enable visual parantheses matching.

#+BEGIN_SRC emacs-lisp
  (show-paren-mode 1)
#+END_SRC

Keep folders clean

#+BEGIN_SRC emacs-lisp
  ;; NOTE: If you want to move everything out of the ~/.emacs.d folder
  ;; reliably, set `user-emacs-directory` before loading no-littering!
                                          ;(setq user-emacs-directory "~/.cache/emacs")

  (use-package no-littering :ensure t)

  ;; no-littering doesn't set this by default so we must place
  ;; auto save files in the same path as it uses for sessions
   (setq auto-save-file-name-transforms
        `((".*" ,(no-littering-expand-var-file-name "auto-save/") t)))

#+END_SRC

Startup Performance

#+BEGIN_SRC emacs-lisp
  ;; The default is 800 kilobytes.  Measured in bytes.
  (setq gc-cons-threshold (* 50 1000 1000))

  (defun efs/display-startup-time ()
    (message "Emacs loaded in %s with %d garbage collections."
             (format "%.2f seconds"
                     (float-time
                      (time-subtract after-init-time before-init-time)))
             gcs-done))

  (add-hook 'emacs-startup-hook #'efs/display-startup-time)
  (setq display-time-default-load-average 1)
#+END_SRC

Config edit.

#+BEGIN_SRC emacs-lisp
  (defun config-visit ()
    (interactive)
    (find-file "~/.config/emacs/config.org"))
  (global-set-key (kbd "C-c e") 'config-visit)
#+END_SRC

Config reload.

#+BEGIN_SRC emacs-lisp
  (defun config-reload ()
    (interactive)
    (org-babel-load-file (expand-file-name "~/.config/emacs/config.org")))
  (global-set-key (kbd "C-c r") 'config-reload)
#+END_SRC

Fix tiling window managers
#+BEGIN_SRC emacs-lisp
  (setq frame-resize-pixelwise t)
#+END_SRC

Text line stuff
#+BEGIN_SRC emacs-lisp
  (setq-default truncate-lines t)
  (setq-default tab-width 4)
  (setq-default fill-column 80)
  (setq sentence-end-double-space nil)
#+END_SRC

Scroll
#+BEGIN_SRC emacs-lisp
  (setq redisplay-dont-pause t
        scroll-margin 1
        scroll-step 1
        scroll-conservatively 10000
        scroll-preserve-screen-position 1)
#+END_SRC

Bells
#+BEGIN_SRC emacs-lisp
  (setq visible-bell t)
  (setq line-move-visual t)
#+END_SRC

Encoding
#+BEGIN_SRC emacs-lisp
  (when (fboundp 'set-charset-priority)
    (set-charset-priority 'unicode))       ; pretty
  (prefer-coding-system 'utf-8)            ; pretty
  (setq locale-coding-system 'utf-8)       ; please
#+END_SRC

* Packages Configuration
** =hungry-delete=
Enable =hungry-delete=.

#+BEGIN_SRC emacs-lisp
  (use-package hungry-delete
    :ensure t
    :config (global-hungry-delete-mode))
#+END_SRC

** =beacon=
Enable =beacon=.

#+BEGIN_SRC emacs-lisp
  (use-package beacon
    :ensure t
    :config (beacon-mode 1))
#+END_SRC

** =rainbow=
Enable =rainbow=.

#+BEGIN_SRC emacs-lisp
  (use-package rainbow-mode
    :ensure t
    :init (add-hook 'prog-mode-hook 'rainbow-mode))
  (use-package rainbow-delimiters
    :ensure t
    :init (rainbow-delimiters-mode 1))
#+END_SRC

** =async=
Enable =async=.

#+BEGIN_SRC emacs-lisp
  (use-package async
    :ensure t
    :init (dired-async-mode 1))
#+END_SRC

** =which-key=
Enable =which-key= everywhere.

#+BEGIN_SRC emacs-lisp
  (use-package which-key :ensure t)
  (which-key-mode)
#+END_SRC


** =evil-mode=
Enable =evil-mode= everywhere.

#+BEGIN_SRC emacs-lisp
  (setq evil-want-C-i-jump nil)
  (use-package evil :ensure t)
  (evil-mode 1)
#+END_SRC

** =company=

Enable =company-mode= everywhere.

#+BEGIN_SRC emacs-lisp
  (use-package company)
  (add-hook 'after-init-hook 'global-company-mode)
#+END_SRC

Use =M-/= for completion.

#+BEGIN_SRC emacs-lisp
  (global-set-key (kbd "M-/") 'company-complete-common)
#+END_SRC

** =company-tabnine=
#+BEGIN_SRC emacs-lisp
  ;;(use-package company-tabnine
  ;;  :ensure t)
  ;;(require 'company-tabnine)
  ;;(add-to-list 'company-backends #'company-tabnine)
  ;;(setq company-idle-delay 0)
  ;;(setq company-show-numbers t)
#+END_SRC

** =magit=

Use magit for git repos managment.

#+BEGIN_SRC emacs-lisp
  (use-package magit
    :ensure t
    :bind ("M-g" . magit-status))
#+END_SRC

** =projectile=

Use projectile for useful funcationality for project management.

#+BEGIN_SRC emacs-lisp
  (use-package projectile :ensure t)
  (projectile-mode +1)
  (define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)
#+END_SRC

** =undo-tree=

Use =undo-tree=.

#+BEGIN_SRC emacs-lisp
  (use-package undo-tree :ensure t)
#+END_SRC

** =darkroom=

Use =darkroom=.

#+BEGIN_SRC emacs-lisp
  (use-package darkroom :ensure t)
  (global-set-key (kbd "<f3>") 'darkroom-mode)
#+END_SRC

** =dashboard=.

#+BEGIN_SRC emacs-lisp
  (use-package dashboard
    :ensure t
    :config
    (dashboard-setup-startup-hook)
    ;;(setq dashboard-startup-banner "~/.emacs.d/img/avatar.png")
    (setq dashboard-items '((recents  . 5)
                            (projects . 5)))
    (setq dashboard-banner-logo-title "ello dere!")
    (setq dashboard-center-content t)
    (setq initial-buffer-choice (lambda () (get-buffer "*dashboard*"))))
#+END_SRC

** =fancy-battery=.
   
#+BEGIN_SRC emacs-lisp
  (use-package fancy-battery
    :ensure t
    :init
    (fancy-battery-mode 1)
    (setq fancy-battery-show-percentage t))
#+END_SRC

** =diminish=

#+BEGIN_SRC emacs-lisp
  (use-package diminish
    :ensure 
    :init
    (diminish 'which-key-mode)
    (diminish 'linum-relative-mode)
    (diminish 'hungry-delete-mode)
    (diminish 'visual-line-mode)
    (diminish 'subword-mode)
    (diminish 'beacon-mode)
    (diminish 'irony-mode)
    (diminish 'page-break-lines-mode)
    (diminish 'auto-revert-mode)
    (diminish 'rainbow-delimiters-mode)
    (diminish 'rainbow-mode)
    (diminish 'yas-minor-mode)
    (diminish 'flycheck-mode))
#+END_SRC

** =sudo-edit=

#+BEGIN_SRC emacs-lisp
  (use-package sudo-edit
    :ensure t
    :bind ("s-e" . sudo-edit))
#+END_SRC

** =avy=
#+BEGIN_SRC emacs-lisp
  (use-package avy
    :ensure t
    :bind
    ("M-s" . avy-goto-char))
#+END_SRC

** =eglot=
#+BEGIN_SRC emacs-lisp
  (use-package eglot
    :ensure t
    :bind)
  (add-hook 'foo-mode-hook 'eglot-ensure)
#+END_SRC

** =focus=
#+BEGIN_SRC emacs-lisp
  (use-package focus
    :ensure t
    :bind)
#+END_SRC

** =LSP=
#+BEGIN_SRC emacs-lisp
  (use-package lsp-mode
    :init
    ;; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l")
    (setq lsp-keymap-prefix "C-c l")
    :hook (;; replace XXX-mode with concrete major-mode(e. g. python-mode)
           (XXX-mode . lsp)
           ;; if you want which-key integration
           (lsp-mode . lsp-enable-which-key-integration))
    :commands lsp)
  ;; optionally
  (use-package lsp-ui :commands lsp-ui-mode)
  ;; if you are helm user
  (use-package helm-lsp :commands helm-lsp-workspace-symbol)
  (use-package lsp-treemacs :commands lsp-treemacs-errors-list)
  ;; optionally if you want to use debugger
  (use-package dap-mode :ensure t)
  ;; (use-package dap-LANGUAGE) to load the dap adapter for your language
  ;; optional if you want which-key integration
  (use-package which-key
    :config
    (which-key-mode))
#+END_SRC

** =org-reveal=
#+BEGIN_SRC emacs-lisp
  (use-package ox-reveal
    :ensure t)
#+END_SRC
** =org-roam=
#+BEGIN_SRC emacs-lisp
  (use-package org-roam
    :ensure t
    :init
    (setq org-roam-v2-ack t)
    :custom
    (org-roam-directory "~/dox/roamnotes")
    (org-roam-completion-everywhere t)
    :bind(("C-c n l" . org-roam-buffer-toggle)
          ("C-c n f" . org-roam-node-find)
          ("C-c n i" . org-roam-node-insert)
          :map org-mode-map
          ("C-M-i" . completion-at-point))
    :config
    (org-roam-setup))
#+END_SRC

** =simple-httpd=
#+BEGIN_SRC emacs-lisp
  (use-package simple-httpd
    :ensure t)
#+END_SRC
** =rainbow-delimiters=
#+BEGIN_SRC emacs-lisp
  (use-package rainbow-delimiters)
#+END_SRC
** =yassnippets=
#+BEGIN_SRC emacs-lisp
  (use-package yasnippet
    :ensure t
    :init
    (yas-global-mode 1))
  (use-package yasnippet-snippets :ensure t)
  (use-package yasnippet-classic-snippets :ensure t)
#+END_SRC
** Environment Specific Packages.
*** Lisp Environment

Use =paredit=.

#+BEGIN_SRC emacs-lisp
  (use-package paredit :ensure t)
#+END_SRC

Use =rainbow-delimiters=.

#+BEGIN_SRC emacs-lisp
  (use-package rainbow-delimiters)
#+END_SRC
*** Web Stuff
#+BEGIN_SRC emacs-lisp
  (use-package web-mode :ensure t)
  (add-hook 'html-mode-hook 'web-mode) ;; Auto-start on any markup modes
  (use-package emmet-mode :ensure t)
  (add-hook 'web-mode-hook  'emmet-mode)
#+END_SRC
*** Org mode
#+BEGIN_SRC emacs-lisp
  (defvar org-directory "~/org/")

  (set-register ?i (cons 'file (concat org-directory "ideas.org")))
  (set-register ?a (cons 'file (concat org-directory "agendas")))

  (setq org-todo-keywords '((type "TODO(t)" "READ(r)" "PROJ(p)"
                                  "CONTACT(c)" "HW(h)" "STUDY(s)" "SOMEDAY(S)"
                                  "|" "DONE(d)" "CANCELLED(C)")))
  (setq org-todo-keyword-faces '(("TODO" nil :foreground "orange1" :inherit fixed-pitch :weight medium)
                                 ("HW" nil :foreground "coral1" :inherit fixed-pitch :weight medium)
                                 ("STUDY" nil :foreground "plum3" :inherit fixed-pitch :weight medium)
                                 ("SOMEDAY" nil :foreground "steel blue" :inherit fixed-pitch)
                                 ("CONTACT" nil :foreground "LightSalmon2" :inherit fixed-pitch :weight medium)
                                 ("READ" nil :foreground "MediumPurple3" :inherit fixed-pitch :weight medium)
                                 ("PROJ" nil :foreground "aquamarine3" :inherit fixed-pitch :weight medium)

                                 ("DONE" nil :foreground "LawnGreen" :inherit fixed-pitch :weight medium)
                                 ("CANCELLED" nil :foreground "dark red" :inherit fixed-pitch :weight medium)))
#+END_SRC

** Completion Frameworks
#+BEGIN_SRC emacs-lisp
  (use-package vertico
    :ensure t
    :init
    (vertico-mode))

  (use-package orderless
    :ensure t
    :init
    (setq completion-styles '(orderless)
          completion-category-defaults nil
          completion-category-overrides '((file (styles partial-completion)))))

  ;; Persist history over Emacs restarts. Vertico sorts by history position.
  (use-package savehist
    :ensure t
    :init
    (savehist-mode))

  ;; A few more useful configurations...
  (use-package emacs
    :init
    ;; Add prompt indicator to `completing-read-multiple'.
    ;; Alternatively try `consult-completing-read-multiple'.
    (defun crm-indicator (args)
      (cons (concat "[CRM] " (car args)) (cdr args)))
    (advice-add #'completing-read-multiple :filter-args #'crm-indicator)

    ;; Do not allow the cursor in the minibuffer prompt
    (setq minibuffer-prompt-properties
          '(read-only t cursor-intangible t face minibuffer-prompt))
    (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)

    ;; Emacs 28: Hide commands in M-x which do not work in the current mode.
    ;; Vertico commands are hidden in normal buffers.
    ;; (setq read-extended-command-predicate
    ;;       #'command-completion-default-include-p)

    ;; Enable recursive minibuffers
    (setq enable-recursive-minibuffers t))

  (use-package marginalia
    :ensure t
    :config (marginalia-mode))

  (use-package consult
    :ensure t
    :general
    ("M-y" 'consult-yank-from-kill-ring
     "C-x b" 'consult-buffer))
  (recentf-mode)

  (setq completion-ignore-case t)
  (setq read-file-name-completion-ignore-case t)
  (use-package orderless
    :ensure t
    :init
    (setq completion-styles '(orderless)))

  (use-package company
    :ensure t
    :config
    (setq company-idle-delay 0)
    (setq company-minimum-prefix-length 3)
    (global-company-mode t))


  (use-package embark
    :ensure t
    :bind
    (("C-." . embark-act)         ;; pick some comfortable binding
     ("C-;" . embark-dwim)        ;; good alternative: M-.
     ("C-h B" . embark-bindings)) ;; alternative for `describe-bindings'

    :init

    ;; Optionally replace the key help with a completing-read interface
    (setq prefix-help-command #'embark-prefix-help-command)

    :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
    ;; if you want to have consult previews as you move around an
    ;; auto-updating embark collect buffer
    :hook
    (embark-collect-mode . consult-preview-at-point-mode))
#+END_SRC
* Programming Environments Configuration

Use 4-spaced characters for tabs by default.

#+BEGIN_SRC emacs-lisp
  (setq-default tab-width 4)
#+END_SRC

Use subword mode.

#+BEGIN_SRC emacs-lisp
  (use-package subword
    :config (global-subword-mode 1))
#+END_SRC

** =C/C++= Environment

Set the tab width when using C/C++ mode.

#+BEGIN_SRC emacs-lisp
  (setq-default c-basic-offset 4)
#+END_SRC

** =Kotlin= Environment

#+BEGIN_SRC emacs-lisp
  (use-package kotlin-mode
    :ensure t)
  (add-to-list 'auto-mode-alist '("\\.kt\\'" . kotlin-mode))
#+END_SRC

** =Lisp= Environment

Uses lisp packages when lisp languages are enabled.

#+BEGIN_SRC emacs-lisp
  (setq lispy-mode-hooks
        '(emacs-lisp-hook lisp-mode-hook))

  (dolist (hook lispy-mode-hooks)
    (add-hook hook (lambda()
                     (setq show-paren-style 'expression)
                     (paredit-mode)
                     (rainbow-delimeters-mode))))
#+END_SRC

Set tab with

** =org-mode= Environment
Enable indentation in =org= source blocks.

#+BEGIN_SRC emacs-lisp
  (setq org-src-tab-acts-natively t)
#+END_SRC

Better org bullets.

#+BEGIN_SRC emacs-lisp
  (use-package org-bullets
    :ensure t
    :config
    (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1))))
#+END_SRC

Flyspell
#+BEGIN_SRC emacs-lisp
  (add-hook 'org-mode-hook 'turn-on-flyspell)
  (add-hook 'org-mode-hook 'turn-on-auto-fill)
#+END_SRC

** =sh= Environment

Indent with 4 spaces.

#+BEGIN_SRC emacs-lisp
  (add-hook 'sh-mode-hook
            (lambda ()
              (setq sh-basic-offset 4
                    sh-indentation 4)))
#+END_SRC

** =markdown= Environment

Enable =markdown=.

#+BEGIN_SRC emacs-lisp
  (use-package markdown-mode
    :ensure t
    :commands (markdown-mode gfm-mode)
    :mode (("README\\.md\\'" . gfm-mode)
           ("\\.md\\'" . markdown-mode)
           ("\\.markdown\\'" . markdown-mode))
    :init (setq markdown-command "multimarkdown"))
#+END_SRC
   
* Personal Configuration
#+BEGIN_SRC emacs-lisp
  (setq user-full-name "ayham"
        user-mail-address "me@ayham.xyz")
#+END_SRC



